Как выполнить фильтрацию запросов в шаблонах django
мне нужно выполнить отфильтрованный запрос из шаблона django, чтобы получить набор объектов, эквивалентных коду python в представлении:
queryset = Modelclass.objects.filter(somekey=foo)
в моем шаблоне я хочу сделать
{% for object in data.somekey_set.FILTER %}
но я просто не могу понять, как написать фильтр.
5 ответов:
вы не можете сделать это, что по дизайну. Авторы фреймворка Django предполагали строгое отделение кода представления от логики данных. Модели фильтрации-это логика данных, а вывод HTML-логика представления.
Итак, у вас есть несколько вариантов. Проще всего сделать фильтрацию, а затем передать результат в
render_to_response
. Или вы можете написать метод в своей модели, чтобы вы могли сказать{% for object in data.filtered_set %}
. Наконец, вы можете написать свой собственный тег шаблона, хотя в этом конкретном случае я не советовал бы.
Я просто добавить дополнительный тег шаблона, как это:
@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 %}
Я сталкиваюсь с этой проблемой на регулярной основе и часто использую решение "добавить метод". Однако есть определенные случаи, когда "добавить метод" или "вычислить его в представлении" не работают (или не работают хорошо). Например, когда вы кэшируете фрагменты шаблона и нуждаетесь в некоторых нетривиальных вычислениях БД для его создания. Вы не хотите выполнять работу с БД, если вам это не нужно, но вы не будете знать, нужно ли вам это, пока вы не погрузитесь в логику шаблона.
некоторые другие возможные решения:
используйте тег шаблона {% expr
as %}, найденный в http://www.djangosnippets.org/snippets/9/ выражение-это любое законное выражение Python с контекстом вашего шаблона в качестве локальной области. измените процессор шаблонов. Jinja2 (http://jinja.pocoo.org/2/) имеет синтаксис, который почти идентичен языку шаблонов Django, но с полной доступной мощностью Python. Это и еще быстрее. Вы можете сделать это оптом, или вы можете ограничить его использование шаблонами, которые вы работают, но используют" более безопасные " шаблоны Django для страниц, поддерживаемых дизайнером.
Это можно решить с помощью тега присваивания:
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)
другой вариант заключается в том, что если у вас есть фильтр, который вы всегда хотите применить, чтобы добавить custom manager на рассматриваемой модели, которая всегда применяет фильтр к возвращаемым результатам.
хорошим примером этого является
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
модель и так не так гибка некоторые из методов, описанных выше.
Comments