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

StackOverflow https://stackoverflow.com/questions/223990

  •  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()
    

    Но опять-таки, этот фильтр применяется ко всем запросам по умолчанию, выполненным в модели <=>, и поэтому он не настолько гибок, как некоторые из методов, описанных выше.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top