Как выполнить фильтрацию запросов в шаблонах django



мне нужно выполнить отфильтрованный запрос из шаблона django, чтобы получить набор объектов, эквивалентных коду python в представлении:



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


в моем шаблоне я хочу сделать



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


но я просто не могу понять, как написать фильтр.

1028   5  

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 %}

Я сталкиваюсь с этой проблемой на регулярной основе и часто использую решение "добавить метод". Однако есть определенные случаи, когда "добавить метод" или "вычислить его в представлении" не работают (или не работают хорошо). Например, когда вы кэшируете фрагменты шаблона и нуждаетесь в некоторых нетривиальных вычислениях БД для его создания. Вы не хотите выполнять работу с БД, если вам это не нужно, но вы не будете знать, нужно ли вам это, пока вы не погрузитесь в логику шаблона.

некоторые другие возможные решения:

  1. используйте тег шаблона {% expr as %}, найденный в http://www.djangosnippets.org/snippets/9/ выражение-это любое законное выражение Python с контекстом вашего шаблона в качестве локальной области.

  2. измените процессор шаблонов. 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

    Ничего не найдено.