장고에서 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])
동적 논리를 사용하여 쿼리를 수행해야 하는 경우 다음과 같은 작업을 수행할 수 있습니다(못생긴 + 테스트되지 않음).
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
'itsource' 카테고리의 다른 글
MS가 파워셸을 만들어 해결한 문제는? (0) | 2023.07.26 |
---|---|
고온 및 저온 관측 가능: '열온' 및 '냉온' 연산자가 있습니까? (0) | 2023.07.26 |
Spring Boot Rest 컨트롤러에서 JWT 토큰 액세스 (0) | 2023.07.21 |
H2 스키마 초기화.SQL 문에 구문 오류가 있습니다. (0) | 2023.07.21 |
플라스크-sqlalchemy 또는 sqlalchemy (0) | 2023.07.21 |