itsource

장고에서 OR 쿼리 필터를 동적으로 구성하는 방법은 무엇입니까?

mycopycode 2023. 7. 21. 21:37
반응형

장고에서 OR 쿼리 필터를 동적으로 구성하는 방법은 무엇입니까?

예제에서 다중 OR 쿼리 필터를 볼 수 있습니다.

Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))

예를 들어, 이는 다음과 같은 결과를 초래합니다.

[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]

그러나 목록에서 이 쿼리 필터를 만들고 싶습니다.어떻게 하는 거지?

예.[1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))

다음과 같이 쿼리를 연결할 수 있습니다.

values = [1,2,3]

# Turn list of values into list of Q objects
queries = [Q(pk=value) for value in values]

# Take one Q object from the list
query = queries.pop()

# Or the Q object with the ones remaining in the list
for item in queries:
    query |= item

# Query the model
Article.objects.filter(query)

더 복잡한 쿼리를 작성하려면 Q() 개체의 상수 Q에 내장된 옵션을 사용할 수도 있습니다.OR과 Q.그리고 다음과 같은 add() 메서드와 함께 사용합니다.

list = [1, 2, 3]
# it gets a bit more complicated if we want to dynamically build
# OR queries with dynamic/unknown db field keys, let's say with a list
# of db fields that can change like the following
# list_with_strings = ['dbfield1', 'dbfield2', 'dbfield3']

# init our q objects variable to use .add() on it
q_objects = Q(id__in=[])

# loop trough the list and create an OR condition for each item
for item in list:
    q_objects.add(Q(pk=item), Q.OR)
    # for our list_with_strings we can do the following
    # q_objects.add(Q(**{item: 1}), Q.OR)

queryset = Article.objects.filter(q_objects)

# sometimes the following is helpful for debugging (returns the SQL statement)
# print queryset.query

파이썬의 축소 함수를 사용하여 데이브 웹의 답변을 작성하는 더 짧은 방법:

# For Python 3 only
from functools import reduce

values = [1,2,3]

# Turn list of values into one big Q objects  
query = reduce(lambda q,value: q|Q(pk=value), values, Q())  

# Query the model  
Article.objects.filter(query)  
from functools import reduce
from operator import or_
from django.db.models import Q

values = [1, 2, 3]
query = reduce(or_, (Q(pk=x) for x in values))

아마도 sql IN 문을 사용하는 것이 더 나을 것입니다.

Article.objects.filter(id__in=[1, 2, 3])

api 참조 쿼리를 참조하십시오.

동적 논리를 사용하여 쿼리를 수행해야 하는 경우 다음과 같은 작업을 수행할 수 있습니다(못생긴 + 테스트되지 않음).

query = Q(field=1)
for cond in (2, 3):
    query = query | Q(field=cond)
Article.objects.filter(query)

문서 참조:

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}

이 방법은 기본 키 검색에만 사용할 수 있지만 이 방법을 사용하려는 것 같습니다.

원하는 것은 다음과 같습니다.

Article.objects.in_bulk([1, 2, 3])

사용하는 솔루션reduce그리고.or_여러 필드로 필터링할 연산자입니다.

from functools import reduce
from operator import or_
from django.db.models import Q

filters = {'field1': [1, 2], 'field2': ['value', 'other_value']}

qs = Article.objects.filter(
   reduce(or_, (Q(**{f'{k}__in': v}) for k, v in filters.items()))
)

추신.f문자열 리터럴 형식의 새 형식입니다.파이썬 3.6에 도입되었습니다.

쿼리할 db 필드를 프로그래밍 방식으로 설정하려는 경우:

import operator
questions = [('question__contains', 'test'), ('question__gt', 23 )]
q_list = [Q(x) for x in questions]
Poll.objects.filter(reduce(operator.or_, q_list))

루프용

values = [1, 2, 3]
q = Q(pk__in=[]) # generic "always false" value
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)

줄이자

from functools import reduce
from operator import or_

values = [1, 2, 3]
q_objects = [Q(pk=val) for val in values]
q = reduce(or_, q_objects, Q(pk__in=[]))
Article.objects.filter(q)

이 두 가지 모두 다음과 같습니다.Article.objects.filter(pk__in=values)

왜죠Q()위험합니다

당신이 원하는 것이 무엇인지 고려하는 것은 중요합니다.values비어 있습니다.로 많은 답변 제공Q()시작 값이 모든 것을 반환하기 때문입니다.Q(pk__in=[])시작 값이 더 좋습니다.이것은 항상 실패하는 Q 객체이며, (복잡한 방정식에서도) 최적화기에 의해 잘 처리됩니다.

Article.objects.filter(Q(pk__in=[]))  # doesn't hit DB
Article.objects.filter(Q(pk=None))    # hits DB and returns nothing
Article.objects.none()                # doesn't hit DB
Article.objects.filter(Q())           # returns everything

만약 당신이 모든 것을 돌려주고 싶다면, 다음과 같이.values비어 있습니다. 다음과 같이 해야 합니다.~Q(pk__in=[])다음과 같은 동작을 보장합니다.

values = []
q = Q()
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # only Tolkien

q &= ~Q(pk__in=[])
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # everything

Q()항상 성공하는 Q 개체가 아닙니다.그것과 관련된 모든 작업은 그것을 완전히 중단시킬 것입니다.

|= 연산자를 사용하여 Q 개체를 사용하여 쿼리를 프로그래밍 방식으로 업데이트할 수 있습니다.

동적 pk 목록용입니다.

pk_list = qs.values_list('pk', flat=True)  # i.e [] or [1, 2, 3]

if len(pk_list) == 0:
    Article.objects.none()

else:
    q = None
    for pk in pk_list:
        if q is None:
            q = Q(pk=pk)
        else:
            q = q | Q(pk=pk)

    Article.objects.filter(q)

최근까지 몰랐던 또 다른 방법은 -QuerySet또한 다음을 재정의합니다.&,|,~등, 연산자.ORQ 개체가 이 질문에 대한 더 나은 해결책이라는 다른 답변도 있지만, 관심/논쟁을 위해 다음을 수행할 수 있습니다.

id_list = [1, 2, 3]
q = Article.objects.filter(pk=id_list[0])
for i in id_list[1:]:
    q |= Article.objects.filter(pk=i)

str(q.query)의 모든 필터가 포함된 하나의 쿼리를 반환합니다.WHERE

동적 필드 이름에 대한 솔루션을 찾았습니다.

def search_by_fields(value, queryset, search_in_fields):
    if value:
        value = value.strip()

    if value:
        query = Q()
        for one_field in search_in_fields:
            query |= Q(("{}__icontains".format(one_field), value))

        queryset = queryset.filter(query)

    return queryset

쉬운..
django.db.dll 가져오기 Q에서 모델 변수 가져오기 = (Q(가시성=1)|(Q(가시성=0)&Q(사용자=셀프.user)) #Tuple 매개 변수={} #dic 순서 = 'create_at' 한계 = 10

Models.objects.filter(*args,**parameters).order_by(order)[:limit]

언급URL : https://stackoverflow.com/questions/852414/how-to-dynamically-compose-an-or-query-filter-in-django

반응형