ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django] orm
    언어/파이썬 & 장고 2016. 7. 8. 17:27

    장고에서 제공하는 모델을 사용하기 위해선 from 앱이름.models import 모델명, 모델명1과 같이 선언해야 합니다.

    먼저 django orm 사용에서 복잡한 쿼리에 대해 적합하지 않습니다. 예를 들어, 두 테이블 간 join을 하기 위해선 foriegn key가 잡혀 있어야만 join이 가능한 상태입니다. 복잡한 쿼리의 같은 경우 orm을 지양하는 것이 좋습니다.

    또한 여기서는 restframework도 같이 설명하고 있기 때문에 레퍼런스를 보고 싶은 분은 아래 링크를 확인해 주시기 바랍니다.

    1. http://www.django-rest-framework.org/
    2. http://www.django-rest-framework.org/api-guide/serializers/

    Select

    Get

    단일 행 결과를 반환하는 model.objects.get()는 타입이 Query Set이 아닌 단일행 (모델타입)으로 나옴

    • 사용은 value_name.column_name 과 같이 . 으로 컬럼 이름을 써서 사용합니다.
    • get() 안에 조건을 제시할 수 있습니다.(sql의 where절 과 동일)
    • get()은 단일행을 반환하므로 다른 method들을 get() 다음에 연결하여 사용할 수 없습니다.
    key = model1.objects.get(pk=pk)
    print(key.name)

    만약 get을 사용했는데 반환되는 값이 1개 이상일 경우 에러가 나옵니다.

    All

      전체 자료를 불러오는 model.objects.all()은 QuerySet 타입으로 반환

    • 사용은 dictionary를 사용하는 것과 동일하게 사용.
    key = model2.objects.all()
    print(key[0]['name'])


    만약 get()과 같이 단일 행의 결과가 존재하지 않을 경우 모델명.DoesNotExist의 exception으로 처리가 되지만 all()과 같은 여러 행이 나오는 경우엔 exception이 아닌 빈값으로 처리가 됩니다.

    Filter

    앞에서 get()은 단일행을 조건을 걸어 출력하는 것이면, filter는 조건에 맞는 여러 행을 출력하는 것입니다. 사용은 model.objects.filter()로 타입은 QuerySet입니다. (objects.all().filter() 와 동일한 기능입니다. (all() 생략) )

    value = key = model2.objects.filter(name='lee')
    print(key[0]['name'])


    get과 filter에 각 조건을 걸 수 있으며 조건은 and로 결합됩니다.

    조건 키워드

     키워드설 명사용예

     __lt / __gt

    __lte / __gte

    보 다 작다 / 보다 크다

    같거나 보다 작다 / 같거나 보다 크다

    id가 1보다 큰 자료 검색

    >>> Department.objects.filter(id__gt=1)

    [<Department: Computer Science>]

     __in주어진 리스트 안에 존재하는 자료 검색

    id 가 2, 3, 5 인 자료 검색

     >>> Department.objects.filter(id__in=[2, 3, 5])
    [<Department: Computer Science>]

     __year / __month / __day해당 년도, 월, 일 자료 검색>>>Entry.objects.filter(pub_date__year=2005)
    __isnull해 당 열의 값이 null 인 자료  검색

    >> Department.objects.filter(dName__isnull=True)

    []

     __contains / __icontains

    해당 열의 값이 지정한 문자열을 포함하는 자료 검색

    (__icontains 는 대소문자를 구별하지 않음)

    >>> Department.objects.filter(dName__contains='puter')

    [<Department: Computer Science>]

     __startswith / __istartswith

    해당 열의 값이 지정한 문자열로 시작하는 자료 검색

    (__istartswith 는 대소문자를 구별하지 않음)

    >>> Department.objects.filter(dName__startswith='Com')
    [<Department: Computer Science>]
     __endswith / __iendswith

    해당 열의 값이 지정한 문자열로 끝나는 자료 검색

    (__iendswith 는 대소문자를 구별하지 않음)

    >>> Department.objects.filter(dName__contains='nce')
    [<Department: Computer Science>]
     __range

    문 자, 숫자, 날짜의 범위를 지정함

    (SQL의 BETWEEN에

    >>> Department.objects.filter(id__range=(2, 10))

    Order by

    model.objects.order_by()로 사용하며 기본 정렬순서는 오름차순 정렬입니다. 내림차순으로 정렬할 경우 컬러명 앞에 -를 붙여 사용합니다.

    value = model.objects.order_by('-pk') # 내림차순 정렬
    value = model.objects.order_by('pk') # 오름차순 정렬

    Value

    model.objects.values()와 같이 사용하며 기능은 sql의 select에 해당합니다. value를 사용하지 않으면 sql의 select * 와 같이 전체 컬럼을 출력합니다.

    value = model.objects.values('pk') # query set 타입으로 pk만 출력

    Aggregate

    sql에서 max, min, count 등과 같이 다중 행을 단일 행으로 출력해주는 기능을 해줍니다.

    model.objects.aggregate()와 같이 사용되며 단일행을 반환하므로 aggregate()뒤에 다른 method를 붙여 사용할 수 없습니다.

    from django.db.models import Max
    value = model.objects.aggregate(temp_name=Max('pk')) # temp_name은 사용자가 임의로 정할 수 있음
    print(value['temp_name'])


    from django.db.models import Max
    from django.db.models.functions import Coalesce
    value = model.objects.aggregate(temp_name=Coalesce(Max('pk'),10000)) # temp_name은 사용자가 임의로 정할 수 있음
    print(value['temp_name'])

    Annotate

    ----------------;;--------------------------


    Insert

    Django Model 사용

    모델을 사용하여 insert를 하는 방법은 2가지가 있습니다. 보통의 경우는 rest framework를 사용해 저장할 값에 대한 validation check를 한 다음 저장하는 형식이 안전하기 때문에 rest framework를 사용하는 것을 권장합니다.

    save() 사용

    data = model2(name='lee')
    data.save() #model2 라는 테이블에 name이 'lee'라는 데이터 insert

    save()를 하지 않을 경우 메모리 상에 저장할 데이터의 Instance만 존재하고 테이블에 저장되지는 않습니다.

    objects.create() 사용

    data = model2.objects.create(name='lee')

    objects.create를 할 경우 .save()를 할 필요가 없이 바로 저장이 됩니다.

    Rest framework 사용

    Django로 rest api를 만드려고 할 때, 가장 널리 쓰이는 프레임워크 중 하나입니다. 해당 프레임워크를 사용해 손쉽게 insert를 할 수 있습니다. (설치 및 사용법은 Django REST Framework에 설명되어 있습니다.)

    serializer = CommonTax1InSerializer(data=json_format_data, partial=True)
    
    if serializer.is_valid():
        serializer.save()
    

    json_format_data는 json(dict)형식의 데이터입니다. 

    partial은 테이블 내의 일부분만 insert할 때, 필요한 아규먼트입니다. 만약 partial을 제외하고 serializer에 명시한 값 중 일부분만 insert하려하면 에러가 나게 됩니다.

    .save()를 하기 위해선 먼저 validation 확인을 한 다음 진행해야 됩니다.


    Update

    Django Model 사용

    단일 업데이트

    먼저 1개 단일 행의 데이터를 변경하는 것은 다음과 같습니다.

    data = model2.objects.get(pk=pk)
    data.name = 'kim'
    data.save()

    insert와 유사하게 save()를 사용합니다. 만약 해당 object가 기존 테이블에 존재하지 않으면 insert 기능을 수행하고, 그렇지 않으면 update 기능을 수행합니다.

    위처럼 get()으로 받아와서 update를 하는 경우는 pk가 단일 컬럼으로 잡혀있는 경우에만 사용이 가능합니다. (여러 컬럼이 묶여 하나의 pk를 이루는 형태에서는 불가능)

    다중 업데이트

    여러 행의 데이터 및 여러 컬럼이 묶여 하나의 pk를 이루는 형태의 테이블에서 데이터를 변경하는 것은 다음과 같습니다.

    model2.objects.filter(name='lee', age='20').update(**update_dict)

    **update_dict에 대한 설명은 다음 parameter (또는 argument) 앞에 *, ** 의미에 정리되어 있습니다.

    Rest framework 사용

    단일 업데이트

    먼저 1개 단일 행의 데이터를 변경하는 것은 다음과 같습니다.

    pk = model2.objects.get(pk=pk)
    serializer = model2(pk, data=json_data)
    if serializer.is_valid():
        serializer.save()

    먼저 업데이트할 단일행을 구한다음, 모델 클래스의 아규먼트로 instance에 pk를 넣고 data에 변경할 값의 json(dict) 값을 넣습니다.

    다중 업데이트

    먼저 다중 행의 데이터를 변경하는 것은 다음과 같습니다.

    queryset = model2.objects.all()
    serializer = BookSerializer(queryset, many=True)
    if serializer.is_valid():
        serializer.save()


    여러 컬럼이 묶여 하나의 pk를 이루고 있는 형태에서 rest framework를 사용해 update를 하려고 할 때 방법이 복잡하기 때문에 django model을 사용하는 것이 낫습니다.


    Delete

    delete는 update와 유사하게 동작하지만 단일 행이나 복수 행 구분없이 똑같이 delete()메소드를 사용합니다. 또한 rest framework나 django model 둘 다 같은 방식을 사용하고 있습니다.

    단일 삭제

    먼저 1개 단일 행의 데이터를 삭제하는 것은 다음과 같습니다.

    pk = model2.objects.get(pk=pk)
    pk.delete()

    다중 삭제

    여러 행 및 쿼리 결과의 데이터를 삭제하는 것은 다음과 같습니다.

    model2.objects.filter(name='lee',age='20').delete()


    댓글