Muszę wykonać filtrowane zapytanie z poziomu szablonu django, aby uzyskać zestaw obiektów odpowiadający kodowi Pythona w widoku:
queryset = Modelclass.objects.filter(somekey=foo)
W moim szablonie chciałbym to zrobić
{% for object in data.somekey_set.FILTER %}
ale po prostu nie mogę się dowiedzieć, jak napisać FILTR.
Po prostu dodaję dodatkowy tag szablonu, taki jak ten:
@register.filter def in_category(things, category): return things.filter(category=category)
Wtedy mogę:
{% for category in categories %} {% for thing in things|in_category:category %} {{ thing }} {% endfor %} {% endfor %}
źródło
'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d
. Jakieś pomysły?Regularnie napotykam ten problem i często korzystam z rozwiązania „dodaj metodę”. Jednak na pewno są przypadki, w których „dodaj metodę” lub „oblicz ją w widoku” nie działa (lub nie działa dobrze). Np. Kiedy buforujesz fragmenty szablonu i potrzebujesz trochę nietrywialnych obliczeń bazy danych, aby je stworzyć. Nie chcesz wykonywać pracy z bazą danych, chyba że musisz, ale nie będziesz wiedział, czy musisz, dopóki nie zagłębisz się w logikę szablonu.
Inne możliwe rozwiązania:
Użyj tagu szablonu {% expr <expression> as <var_name>%} znajdującego się pod adresem http://www.djangosnippets.org/snippets/9/ Wyrażenie to dowolne zgodne z prawem wyrażenie Pythona z kontekstem szablonu jako zakresem lokalnym.
Zmień procesor szablonów. Jinja2 ( http://jinja.pocoo.org/2/ ) ma składnię prawie identyczną z językiem szablonów Django, ale z pełną mocą Pythona. Jest też szybszy. Możesz to zrobić hurtowo lub ograniczyć jego użycie do szablonów, nad którymi pracujesz, ale użyj „bezpieczniejszych” szablonów Django dla stron obsługiwanych przez projektanta.
źródło
Inną opcją jest to, że jeśli masz filtr, który zawsze chcesz zastosować, możesz dodać niestandardowego menedżera do danego modelu, który zawsze stosuje filtr do zwracanych wyników.
Dobrym przykładem jest
Event
model, w którym dla 90% zapytań, które wykonujesz na modelu, będziesz chciał czegoś takiegoEvent.objects.filter(date__gte=now)
, tj. Normalnie jesteś zainteresowanyEvents
tym, co nadchodzi. To wyglądałoby tak:class EventManager(models.Manager): def get_query_set(self): now = datetime.now() return super(EventManager,self).get_query_set().filter(date__gte=now)
A w modelu:
class Event(models.Model): ... objects = EventManager()
Ale znowu, to stosuje ten sam filtr do wszystkich domyślnych zapytań wykonywanych w
Event
modelu, więc nie jest tak elastyczny w przypadku niektórych technik opisanych powyżej.źródło
Można to rozwiązać za pomocą tagu przypisania:
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)
źródło
Dla każdego, kto szuka odpowiedzi w 2020 roku. U mnie to zadziałało.
W widokach:
class InstancesView(generic.ListView): model = AlarmInstance context_object_name = 'settings_context' queryset = Group.objects.all() template_name = 'insta_list.html' @register.filter def filter_unknown(self, aVal): result = aVal.filter(is_known=False) return result @register.filter def filter_known(self, aVal): result = aVal.filter(is_known=True) return result
W szablonie:
{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}
W pseudokodzie:
For each in model.child_object|view_filter:filter_arg
Mam nadzieję, że to pomoże.
źródło