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