수색…


소개

F () 표현식은 장고가 파이썬 객체를 사용하여 파이썬 메모리에 값을 가져 오지 않고 데이터베이스의 모델 필드 또는 주석이 달린 컬럼의 값을 참조하는 방법입니다. 이를 통해 개발자는 특정 경쟁 조건을 피하고 모델 필드 값을 기반으로 결과를 필터링 할 수 있습니다.

통사론

  • django.db.models의 가져 오기 F

경쟁 조건 피하기

경쟁 조건이 무엇인지 모르는 경우이 질의 응답 질문을 보십시오.

다음 코드는 경쟁 조건의 영향을받을 수 있습니다.

article = Article.objects.get(pk=69)
article.views_count += 1
article.save()

views_count1337 일 경우 다음과 같은 쿼리가 발생합니다.

UPDATE app_article SET views_count = 1338 WHERE id=69

두 클라이언트가 Article.objects.get(pk=69) 기사에 액세스하면 두 번째 HTTP 요청 article.save() 실행하기 전에 Article.objects.get(pk=69) 를 실행한다는 결과 발생할 수 있습니다 . 따라서 두 요청은 views_count = 1337 , 증분 및 views_count = 1338 을 데이터베이스에 저장 views_count = 1338 실제로는 1339 입니다.

이 문제를 해결하려면 F() 표현식을 사용하십시오.

article = Article.objects.get(pk=69)
article.views_count = F('views_count') + 1
article.save()

반면에 이것은 다음과 같은 쿼리를 발생시킵니다.

UPDATE app_article SET views_count = views_count + 1 WHERE id=69

대량으로 쿼리 세트 업데이트하기

id 51 가진 저자의 모든 기사에서 2 개의 상향 전치를 제거하고 싶다고 가정 해 봅시다.
파이썬에서만이 작업을 수행하면 N 쿼리 ( N 은 쿼리 세트의 기사 수)를 실행합니다.

for article in Article.objects.filter(author_id=51):
    article.upvotes -= 2
    article.save()
    # Note that there is a race condition here but this is not the focus
    # of this example.

파이썬으로 모든 기사를 가져 오지 않고 루핑하고 upvotes를 줄이며 각각의 업데이트 된 기사를 다시 데이터베이스에 저장하는 대신 다른 방법이 있다면 어떨까요?
F() 표현식을 사용하면 하나의 쿼리에서이를 수행 할 수 있습니다.

Article.objects.filter(author_id=51).update(upvotes=F('upvotes') - 2)

다음 SQL 쿼리에서 번역 할 수 있습니다.

UPDATE app_article SET upvotes = upvotes - 2 WHERE author_id = 51

이게 왜 더 좋은가요?

  • 파이썬이 작업을 수행하는 대신, 우리는 데이터베이스에로드를 전달합니다.이 쿼리는 그러한 쿼리를 만들기 위해 미세 조정됩니다.
  • 원하는 결과를 얻기 위해 필요한 데이터베이스 쿼리의 수를 효과적으로 줄입니다.

필드 사이의 산술 연산 실행

F() 표현식을 사용하여 모형 필드에서 산술 연산 ( + , - , * 등)을 실행하여 이들 사이의 대수 조회 / 연결을 정의 할 수 있습니다.

  • 모델을 다음과 같이 설정하십시오.

    class MyModel(models.Model):
        int_1 = models.IntegerField()
        int_2 = models.IntegerField()
    
  • 이제 int_1int_2 필드가이 방정식을 만족하는 MyModel 테이블의 모든 객체를 검색하려고한다고 가정합니다. int_1 + int_2 >= 5 . annotate()filter() 를 사용하면 다음을 얻습니다.

    result = MyModel.objects.annotate(
                 diff=F(int_1) + F(int_2)
             ).filter(diff__gte=5)
    

    result 에는 이제 위에서 언급 한 모든 객체가 포함됩니다.

이 예제에서는 Integer 필드를 사용하지만이 메서드는 산술 연산을 적용 할 수있는 모든 필드에서 작동합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow