장고 템플릿에서 쿼리 필터링을 수행하는 방법


82

뷰 내에서 파이썬 코드에 해당하는 객체 세트를 얻으려면 django 템플릿 내에서 필터링 된 쿼리를 수행해야합니다.

queryset = Modelclass.objects.filter(somekey=foo)

내 템플릿에서 내가하고 싶습니다

{% for object in data.somekey_set.FILTER %}

하지만 FILTER를 작성하는 방법을 찾을 수없는 것 같습니다.

답변:


119

당신은 이것을 할 수 없습니다. Django 프레임 워크 작성자는 데이터 논리에서 프레젠테이션 코드를 엄격하게 분리하려고했습니다. 필터링 모델은 데이터 로직이고 HTML 출력은 프리젠 테이션 로직입니다.

따라서 몇 가지 옵션이 있습니다. 가장 쉬운 방법은 필터링을 수행 한 다음 결과를에 전달하는 것 render_to_response입니다. 또는라고 말할 수 있도록 모델에 메소드를 작성할 수 있습니다 {% for object in data.filtered_set %}. 마지막으로, 고유 한 템플릿 태그를 작성할 수 있지만,이 특정 경우에는 이에 대해 권장하지 않습니다.


2
Hello People은 지금 2014입니다! 약 6 년 후 JS 라이브러리는 큰 진전을 이루었고, 그리 크지 않은 데이터의 필터링은 멋진 자바 스크립트 라이브러리 또는 최소한 AJAX-ed를 지원하는 클라이언트 측에서 수행되어야합니다.
andilabs 2014 년

1
@andi : 예를 들어 테이블에있는 수천 개의 행과 같이 적당히 큰 데이터 세트에도 동의합니다. 수백만 개의 행이있는 데이터베이스에서 작업 해 왔지만 여전히 서버 측 필터링을위한 장소가 있습니다. :)
Eli Courtwright

물론, 나는 단지 몇 K의 행을 다루는 사람들을 모두 지적하고 싶었습니다. 사용자를위한 좋은 상호 작용 경험이 브라우저에서 일어날 수 있다는 것입니다. 그리고 거대한 데이터 세트를 다루는 사람들에게도 일부 하이브리드 aproach는 좋은 솔루션이 될 수 있습니다. 예를 들어 서버 측에서 몇 M에서 몇 K로 필터링하고이 몇 K 내부의 다른 직원은 클라이언트 측에서 수행합니다.
andilabs

9
@andi 클라이언트 측에서 수행 되지 않는 권한을 기반으로 콘텐츠를 필터링하는 상황을 제외하고 . 권리?

38

다음과 같이 추가 템플릿 태그를 추가합니다.

@register.filter
def in_category(things, category):
    return things.filter(category=category)

그런 다음 할 수 있습니다.

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}

이 솔루션을 시도하고 있지만 오류가 계속 발생합니다 'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d. 어떤 아이디어?
diosney

12

정기적으로이 문제가 발생하고 "방법 추가"솔루션을 자주 사용합니다. 그러나 "메서드 추가"또는 "뷰에서 계산"이 작동하지 않거나 제대로 작동하지 않는 경우가 있습니다. 예를 들어 템플릿 조각을 캐싱하고 그것을 생성하기 위해 사소하지 않은 DB 계산이 필요할 때. 필요한 경우가 아니면 DB 작업을 수행하고 싶지 않지만 템플릿 논리에 깊이 들어가기 전까지는 필요한지 알 수 없습니다.

다른 가능한 솔루션 :

  1. http://www.djangosnippets.org/snippets/9/에 있는 {% expr <expression> as <var_name> %} 템플릿 태그를 사용합니다 . 표현식은 템플릿의 컨텍스트를 로컬 범위로 사용하는 합법적 인 Python 표현식입니다.

  2. 템플릿 프로세서를 변경하십시오. Jinja2 ( http://jinja.pocoo.org/2/ )에는 Django 템플릿 언어와 거의 동일한 구문이 있지만 완전한 Python 기능을 사용할 수 있습니다. 또한 더 빠릅니다. 이 도매를 할 수있는, 또는 당신은 템플릿의 사용을 제한 할 수 당신이 작업하고, 그러나 디자이너 유지 페이지에 대한 장고의 "안전"템플릿을 사용합니다.


9

다른 옵션은 항상 적용하려는 필터가있는 경우 반환 된 결과에 항상 필터를 적용 하는 사용자 지정 관리자 를 해당 모델에 추가하는 것 입니다.

이것의 좋은 예는 것입니다 Event당신이 뭔가를 원하는하고자하는 모델을 할 쿼리의 90 %를 모델 Event.objects.filter(date__gte=now)당신을 즉, 일반적으로 관심 Events이 곧입니다. 이것은 다음과 같습니다.

class EventManager(models.Manager):
    def get_query_set(self):
        now = datetime.now()
        return super(EventManager,self).get_query_set().filter(date__gte=now)

그리고 모델에서 :

class Event(models.Model):
    ...
    objects = EventManager()

그러나 이것은 Event모델에서 수행되는 모든 기본 쿼리에 대해 동일한 필터를 적용 하므로 위에서 설명한 기술 중 일부는 유연하지 않습니다.


9

이것은 할당 태그로 해결할 수 있습니다.

from django import template

register = template.Library()

@register.assignment_tag
def query(qs, **kwargs):
    """ template tag which allows queryset filtering. Usage:
          {% query books author=author as mybooks %}
          {% for book in mybooks %}
            ...
          {% endfor %}
    """
    return qs.filter(**kwargs)

3
assignment_tag가 Django 2.0에서 제거되었습니다
Andreas Bergström

1

2020 년에 답을 찾고있는 모든 사람에게. 이것은 저에게 효과적이었습니다.

보기에서 :

 class InstancesView(generic.ListView):
        model = AlarmInstance
        context_object_name = 'settings_context'
        queryset = Group.objects.all()
        template_name = 'insta_list.html'

        @register.filter
        def filter_unknown(self, aVal):
            result = aVal.filter(is_known=False)
            return result

        @register.filter
        def filter_known(self, aVal):
            result = aVal.filter(is_known=True)
            return result

템플릿에서 :

{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}

의사 코드에서 :

For each in model.child_object|view_filter:filter_arg

도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.