[python] 여러 인수가있는 필터와 장고의 체인 필터의 차이점

Django에서 다중 인수가있는 필터와 체인 필터의 차이점은 무엇입니까?



답변

생성 된 SQL 문에서 볼 수 있듯이 일부는 의심 할 수있는 “OR”이 아닙니다. WHERE 및 JOIN이 배치되는 방법입니다.

예제 1 (동일한 조인 된 테이블) : https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships에서

Blog.objects.filter(
       entry__headline__contains='Lennon',
       entry__pub_date__year=2008)

이렇게하면 이 쿼리에서 기대할 수있는 두 가지 항목이 모두 있는 모든 블로그가 제공됩니다 (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008).

결과:

Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}

예 2 (체인)

Blog.objects.filter(
       entry__headline__contains='Lennon'
           ).filter(
       entry__pub_date__year=2008)

이것은 예제 1의 모든 결과를 포함하지만 약간 더 많은 결과를 생성합니다. 먼저 모든 블로그를 (entry__headline__contains='Lennon')필터링 한 다음 결과 필터에서 필터링하기 때문 (entry__pub_date__year=2008)입니다.

차이점은 다음과 같은 결과도 제공한다는 것입니다.

여러 항목이있는 단일 블로그

{entry.headline: '**Lennon**', entry.pub_date: 2000},
{entry.headline: 'Bill', entry.pub_date: **2008**}

첫 번째 필터가 평가 될 때 첫 번째 항목 때문에 책이 포함됩니다 (일치하지 않는 다른 항목이 있더라도). 두 번째 필터가 평가되면 두 번째 항목 때문에 책이 포함됩니다.

하나의 테이블 : 그러나 쿼리에 Yuji 및 DTing의 예와 같이 조인 된 테이블이 포함되지 않은 경우. 결과는 동일합니다.


답변

“multiple arguments filter-query”의 결과가 “chained-filter-query”와 다른 경우는 다음과 같습니다.

참조 개체 및 관계를 기반으로 참조 개체를 선택하는 것은 일대 다 (또는 다 대다)입니다.

여러 필터 :

    Referenced.filter(referencing1_a=x, referencing1_b=y)
    #  same referencing model   ^^                ^^

체인 필터 :

    Referenced.filter(referencing1_a=x).filter(referencing1_b=y)

두 쿼리 모두 서로 다른 결과를 출력 할 수 있습니다.
referencing-model의 한 행 이상이 referenced-model의 Referencing1동일한 행을 참조 할 수있는 경우 Referenced. 이 경우에 할 수있다 Referenced:
Referencing1이 중 하나를 1 : N (일대) 또는 N : (많은 많은) M 관계 선박.

예:

내 응용 프로그램 my_company에는 두 가지 모델 EmployeeDependent. 의 직원은 my_company부양 가족보다 많을 수 있습니다 (즉, 부양 가족은 한 직원의 아들 / 딸이 될 수 있지만 직원은 둘 이상의 아들 / 딸을 가질 수 있습니다).
Ehh, 남편 아내처럼 둘 다 my_company. 1 : m 예를 들었습니다.

그래서, Employee참조 모델이 더 많이 참조 할 수있는 참조 Dependent모델입니다. 이제 다음과 같이 관계 상태를 고려하십시오.

Employee:        Dependent:
+------+        +------+--------+-------------+--------------+
| name |        | name | E-name | school_mark | college_mark |
+------+        +------+--------+-------------+--------------+
| A    |        | a1   |   A    |          79 |           81 |
| B    |        | b1   |   B    |          80 |           60 |
+------+        | b2   |   B    |          68 |           86 |
                +------+--------+-------------+--------------+

Dependent a1는 직원을 의미 A하고 종속적 b1, b2참조는 직원을 의미 B합니다.

이제 내 쿼리는 다음과 같습니다.

대학과 학교 모두에서 아들 / 딸이있는 직원이 모두 구별 점수 (예 : 75 % 이상)를 가지고 있습니까?

>>> Employee.objects.filter(dependent__school_mark__gte=75,
...                         dependent__college_mark__gte=75)

[<Employee: A>]

출력은 ‘A’종속 ‘a1’은 대학과 학교 모두에서 구별 표시가 있으며 직원 ‘A’에 종속됩니다. 참고 ‘B’는 ‘B’자녀의 네더가 대학과 학교 모두에서 구별 마크가 있기 때문에 선택되지 않았습니다. 관계형 대수 :

종업원 (school_mark> = 75 AND college_mark> = 75) 종속

둘째, 쿼리가 필요한 경우 :

부양 가족 중 일부가 대학과 학교에서 구별 마크가있는 모든 직원을 찾으십니까?

>>> Employee.objects.filter(
...             dependent__school_mark__gte=75
...                ).filter(
...             dependent__college_mark__gte=75)

[<Employee: A>, <Employee: B>]

이번에 ‘B’는 ‘B’가 두 명의 자녀 (한 명 이상!)가 있고, 한 명은 학교 ‘b1’에서 구별 마크가 있고 다른 하나는 대학 ‘b2’에서 구별 마크가 있기 때문에 선택되었습니다.
필터 순서는 중요하지 않습니다. 위의 쿼리를 다음과 같이 작성할 수도 있습니다.

>>> Employee.objects.filter(
...             dependent__college_mark__gte=75
...                ).filter(
...             dependent__school_mark__gte=75)

[<Employee: A>, <Employee: B>]

결과는 동일합니다! 관계형 대수는 다음과 같습니다.

(직원 (school_mark> = 75) 에 따라 다름) (college_mark> = 75) 종속

참고 :

dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75)
dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)

동일한 결과를 출력합니다. [<Dependent: a1>]

Django에서 생성 한 대상 SQL 쿼리를 확인 print qd1.query하고 print qd2.query둘 다 동일합니다 (Django 1.6).

그러나 의미 상 둘 다 나에게 다릅니다 . 첫 번째는 간단한 섹션 σ [school_mark> = 75 AND college_mark> = 75] (종속) 처럼 보이고 두 번째는 느린 중첩 쿼리처럼 보입니다. σ [school_mark> = 75][college_mark> = 75] (종속)).

필요한 경우 코드 @codepad

btw, 그것은 문서 @ Spanning 다중 값 관계에 제공 됩니다. 방금 예제를 추가했습니다. 새로운 사람에게 도움이 될 것이라고 생각합니다.


답변

대부분의 경우 쿼리에 대해 가능한 결과 집합은 하나만 있습니다.

체인 필터는 m2m을 다룰 때 사용됩니다.

이걸 고려하세요:

# will return all Model with m2m field 1
Model.objects.filter(m2m_field=1)

# will return Model with both 1 AND 2    
Model.objects.filter(m2m_field=1).filter(m2m_field=2)

# this will NOT work
Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))

다른 예도 환영합니다.


답변

성능 차이가 큽니다. 그것을 시도하고보십시오.

Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)

의외로 느립니다

Model.objects.filter(condition_a, condition_b, condition_c)

효과적인 Django ORM 에서 언급했듯이 ,

  • QuerySet은 메모리에 상태를 유지합니다.
  • 체이닝은 복제를 트리거하고 해당 상태를 복제합니다.
  • 불행히도 QuerySet은 많은 상태를 유지합니다.
  • 가능하면 두 개 이상의 필터를 연결하지 마십시오.


답변

연결 모듈을 사용하여 비교할 원시 SQL 쿼리를 볼 수 있습니다. Yuji가 설명했듯이 대부분은 다음과 같이 동일합니다.

>>> from django.db import connection
>>> samples1 = Unit.objects.filter(color="orange", volume=None)
>>> samples2 = Unit.objects.filter(color="orange").filter(volume=None)
>>> list(samples1)
[]
>>> list(samples2)
[]
>>> for q in connection.queries:
...     print q['sql']
... 
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
>>> 


답변

이 페이지에서 여러 체인 필터를 사용하여 django 쿼리 세트를 동적으로 빌드하는 방법을 찾고 있지만 필터가 AND대신 유형 이어야하는 경우 Q 객체를OR 사용하는 것이 좋습니다. .

예 :

# First filter by type.
filters = None
if param in CARS:
  objects = app.models.Car.objects
  filters = Q(tire=param)
elif param in PLANES:
  objects = app.models.Plane.objects
  filters = Q(wing=param)

# Now filter by location.
if location == 'France':
  filters = filters & Q(quay=location)
elif location == 'England':
  filters = filters & Q(harbor=location)

# Finally, generate the actual queryset
queryset = objects.filter(filters)


답변

a와 b가 필요한 경우

and_query_set = Model.objects.filter(a=a, b=b)

a와 b가 필요한 경우

chaied_query_set = Model.objects.filter(a=a).filter(b=b)

공식 문서 :
https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

관련 게시물 : Django에서 다중 filter () 연결, 이것이 버그입니까?