Q, F expression

Jinhyeon Son·2020년 5월 9일
0

개념

목록 보기
15/26

Q() for complex lookup

django.db.models.Q 객체는 get(), exclude(), filter()와 같은
키워드 인자를 전달받을 수 있는 django query 메소드의 인자를 
캡슐화하여 좀 더 복잡한 query를 만드는 데 사용하는 객체이다
예를 들면 WHERE문에서의 AND, OR 조건과 조건에 대한 NOT 연산 등을
적용할 수 있다

사용

  • AND
    Q(questionstartswith='Who') & Q(questionstartswith='What')
    Q(questionstartswith='Who'), Q(questionstartswith='What')

  • OR
    Q(questionstartswith='Who') | Q(questionstartswith='What')

  • NOT
    ~Q(question__startswith='Who')

Q객체의 리턴값은 위치인자이지만 키워드 인자처럼 동작한다
그렇기 때문에

Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith='Who',
) # 이 코드는 제대로 동작하지만

Poll.objects.get(
    question__startswith='Who',
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
) # 이 코드는 syntax error가 발생한다

F()

django.db.models.F 객체는 모델의 속성값에 대한 maneuver를
python 메모리로 캐시하지 않고 DB에서 처리할 때 사용하는 객체이다

이해

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

django는 F() 인스턴스를 만나면 뒤에 이어지는 python operator를
override하여 F('stories_filed') + 1 자체를 query한다
그렇기 때문에 python은 reporter.stories_filed의 값을 fetch해오지 않아
값을 알수 없다

주의

F 객체를 사용하여 DB의 값을 직접 조정하였을 경우
다음과 같은 방법으로 model객체를 리로드 해야한다

reporter = Reporters.objects.get(pk=reporter.pk)
# or
reporter.refresh_from_db()

응용

F() 인스턴스를 QuerySet에 적용할 수 있다

reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)

Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)

또한 F() 인스턴스를 orm query 메소드의 축약에 사용할 수도 있다

Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))

0개의 댓글