programing

장고에서 동적 필드 룩업으로 쿼리 세트를 어떻게 필터링합니까?

magicmemo 2023. 7. 15. 10:01
반응형

장고에서 동적 필드 룩업으로 쿼리 세트를 어떻게 필터링합니까?

클래스 지정:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=20)

동적 인수를 기반으로 필터링하는 쿼리 세트를 사용하는 것이 가능합니까?예:

 # Instead of:
 Person.objects.filter(name__startswith='B')
 # ... and:
 Person.objects.filter(name__endswith='B')

 # ... is there some way, given:
 filter_by = '{0}__{1}'.format('name', 'startswith')
 filter_value = 'B'

 # ... that you can run the equivalent of this?
 Person.objects.filter(filter_by=filter_value)
 # ... which will throw an exception, since `filter_by` is not
 # an attribute of `Person`.

Python의 인수 확장은 이 문제를 해결하는 데 사용될 수 있습니다.

kwargs = {
    '{0}__{1}'.format('name', 'startswith'): 'A',
    '{0}__{1}'.format('name', 'endswith'): 'Z'
}

Person.objects.filter(**kwargs)

이것은 매우 일반적이고 유용한 파이썬 관용구입니다.

단순화된 예:

장고 조사 앱에서 등록된 사용자를 보여주는 HTML 선택 목록을 원했습니다.그러나 등록된 사용자가 5000명이기 때문에 쿼리 기준에 따라 목록을 필터링하는 방법이 필요했습니다(예: 특정 워크샵을 완료한 사용자).설문조사 요소를 재사용하기 위해서는 설문조사 질문을 작성하는 사람이 해당 질문에 해당 기준을 적용할 수 있어야 했습니다(질문을 앱에 하드 코딩하고 싶지 않음).

제가 생각해 낸 솔루션은 100% 사용자 친화적이지는 않지만(쿼리를 작성하려면 기술자의 도움이 필요함) 문제를 해결합니다.질문을 작성할 때 편집자는 사전을 사용자 정의 필드에 입력할 수 있습니다. 예:

{'is_staff':True,'last_name__startswith':'A',}

해당 문자열은 데이터베이스에 저장됩니다.보기 코드에서 다음과 같이 반환됩니다.self.question.custom_query그것의 값은 사전처럼 보이는 문자열입니다.eval()이 있는 실제 사전으로 다시 변환한 다음 **kwargs:

kwargs = eval(self.question.custom_query)
user_list = User.objects.filter(**kwargs).order_by("last_name")   

추가 코드 요소에 대한 추가 요청을 한 이전 답변을 연장하기 위해 Q와 함께 코드에서 사용 중인 일부 작업 코드를 추가합니다.요청에 따라 다음과 같은 필드를 필터링할 수 있습니다.

publisher_id
date_from
date_until

이러한 필드는 쿼리에 나타날 수 있지만 누락될 수도 있습니다.

초기 쿼리 집합 실행 후 추가로 필터링할 수 없는 집계된 쿼리의 필드를 기반으로 필터를 작성하는 방법은 다음과 같습니다.

# prepare filters to apply to queryset
filters = {}
if publisher_id:
    filters['publisher_id'] = publisher_id
if date_from:
    filters['metric_date__gte'] = date_from
if date_until:
    filters['metric_date__lte'] = date_until

filter_q = Q(**filters)

queryset = Something.objects.filter(filter_q)...

제가 이것을 파헤치는 데 꽤 많은 시간을 썼기 때문에 이것이 도움이 되길 바랍니다.

편집:

추가적인 이점으로 목록을 사용할 수도 있습니다.예를 들어 publisher_id 대신 publisher_ids라는 목록이 있는 경우 다음 코드를 사용할 수 있습니다.

if publisher_ids:
    filters['publisher_id__in'] = publisher_ids

Django.db.models.Q는 바로 당신이 장고 방식으로 원하는 것입니다.

이것은 제가 보기에 훨씬 더 이해하기 쉬운 것 같습니다.

kwargs = {
    'name__startswith': 'A',
    'name__endswith': 'Z',
    ***(Add more filters here)***

}
Person.objects.filter(**kwargs)

매우 복잡한 검색 양식은 일반적으로 단순한 모델이 이를 파헤치려고 한다는 것을 나타냅니다.

열 이름 및 작업에 대한 값을 정확히 어떻게 얻을 것으로 예상합니까?▁of의 값은 요?'name'하나의'startswith'?

 filter_by = '%s__%s' % ('name', 'startswith')
  1. "검색" 양식?뭐라고요? 이름 목록에서 이름을 고르시겠습니까?작업 목록에서 작업을 선택하시겠습니까?개방형이지만 대부분의 사람들은 이것이 혼란스럽고 사용하기 어렵다고 생각합니다.

    몇 개의 열에 이런 필터가 있습니까? 6? 12? 18?

    • 몇 개요? 복잡한 선택 목록은 말이 안 됩니다.몇 개의 필드와 몇 개의 if 문이 의미가 있습니다.
    • 큰 숫자?당신의 모델은 제대로 들리지 않습니다.필드는 실제로 열이 아닌 다른 테이블의 행에 대한 키인 것처럼 들립니다.
  2. 특정 필터 버튼.잠깐만...그게 장고 관리자가 일하는 방식입니다.특정 필터는 단추로 변환됩니다.그리고 위와 같은 분석이 적용됩니다.몇 가지 필터가 적합합니다.필터 수가 많다는 것은 일반적으로 첫 번째 정규 양식 위반을 의미합니다.

유사한 필드가 많다는 것은 행이 더 많고 필드가 더 적어야 한다는 것을 의미하는 경우가 많습니다.

언급URL : https://stackoverflow.com/questions/310732/in-django-how-does-one-filter-a-queryset-with-dynamic-field-lookups

반응형