2008-10-21 4 views
62

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

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

В моем шаблоне я хотел бы сделать

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

но я просто не могу понять, как писать ФИЛЬТР.

ответ

98

Вы не можете сделать это, это по дизайну. Авторы проекта Django предполагали строгое разделение кода представления от логики данных. Фильтрация моделей - логика данных, а вывод HTML - логика представления.

Итак, у вас есть несколько вариантов. Проще всего сделать фильтрацию, а затем передать результат render_to_response. Или вы можете написать метод в своей модели, чтобы вы могли сказать {% for object in data.filtered_set %}. Наконец, вы можете написать свой собственный тег шаблона, хотя в этом конкретном случае я бы посоветовал это сделать.

+2

Спасибо за прояснение концепции дизайна django. Я использую подход метода модели. – Ber 2008-10-22 00:25:25

+2

Привет, народ, сейчас 2014! Примерно через 6 лет библиотеки JS достигли огромного прогресса, и фильтрация не экстремально большого количества данных должна быть выполнена на стороне клиента с поддержкой некоторой красивой библиотеки сценариев java или, по крайней мере, AJAX-ed. – andi 2014-05-12 18:37:30

11

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

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

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

  2. Измените свой процессор шаблонов. Jinja2 (http://jinja.pocoo.org/2/) имеет синтаксис, который почти идентичен языку шаблонов Django, но с полной мощностью Python. Это также быстрее. Вы можете делать эту оптовую торговлю, или вы можете ограничить ее использование шаблонами, которые вы работаете, но используйте «безопасные» шаблоны Django для страниц, поддерживаемых дизайнерами.

6

Другой вариант заключается в том, что если у вас есть фильтр, который всегда необходимо применить, чтобы добавить 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 модели и поэтому не столь гибкая часть описанные выше.

8

Это может быть решена с помощью тега присваивания:

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) 
22

Я просто добавить дополнительный тег шаблона, как это:

@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 %} 
Смежные вопросы