Ich muss eine gefilterte Abfrage aus einer Django-Vorlage heraus ausführen, um eine Reihe von Objekten zu erhalten, die dem Python-Code in einer Ansicht entsprechen:
queryset = Modelclass.objects.filter(somekey=foo)
In meiner Vorlage möchte ich tun
{% for object in data.somekey_set.FILTER %}
aber ich kann einfach nicht herausfinden, wie man FILTER schreibt.
Ich füge einfach ein zusätzliches Vorlagen-Tag wie das folgende hinzu:
@register.filter def in_category(things, category): return things.filter(category=category)
Dann kann ich tun:
{% for category in categories %} {% for thing in things|in_category:category %} {{ thing }} {% endfor %} {% endfor %}
quelle
'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d
. Irgendwelche Ideen?Ich stoße regelmäßig auf dieses Problem und verwende häufig die Lösung "Methode hinzufügen". Es gibt jedoch definitiv Fälle, in denen "Methode hinzufügen" oder "In der Ansicht berechnen" nicht funktioniert (oder nicht gut funktioniert). Zum Beispiel, wenn Sie Vorlagenfragmente zwischenspeichern und eine nicht triviale DB-Berechnung benötigen, um sie zu erstellen. Sie möchten die DB-Arbeit nicht ausführen, es sei denn, Sie müssen, aber Sie werden nicht wissen, ob Sie dies tun müssen, bis Sie tief in der Vorlagenlogik sind.
Einige andere mögliche Lösungen:
Verwenden Sie das Vorlagen-Tag {% expr <Ausdruck> als <var_name>%} unter http://www.djangosnippets.org/snippets/9/. Der Ausdruck ist ein beliebiger legaler Python-Ausdruck mit dem Kontext Ihrer Vorlage als lokalem Bereich.
Ändern Sie Ihren Vorlagenprozessor. Jinja2 ( http://jinja.pocoo.org/2/ ) verfügt über eine Syntax, die fast identisch mit der Django-Vorlagensprache ist, jedoch über die volle Python-Leistung verfügt. Es ist auch schneller. Sie können dies im Großhandel tun oder die Verwendung auf Vorlagen beschränken, an denen Sie arbeiten, aber die "sichereren" Vorlagen von Django für vom Designer verwaltete Seiten verwenden.
quelle
Die andere Option besteht darin, dass Sie, wenn Sie einen Filter haben, den Sie immer anwenden möchten, dem betreffenden Modell einen benutzerdefinierten Manager hinzufügen , der den Filter immer auf die zurückgegebenen Ergebnisse anwendet.
Ein gutes Beispiel hierfür ist ein
Event
Modell, bei dem Sie für 90% der Abfragen, die Sie an dem Modell durchführen, so etwas wie möchtenEvent.objects.filter(date__gte=now)
, dh Sie sind normalerweise daran interessiertEvents
. Das würde so aussehen:class EventManager(models.Manager): def get_query_set(self): now = datetime.now() return super(EventManager,self).get_query_set().filter(date__gte=now)
Und im Modell:
class Event(models.Model): ... objects = EventManager()
Dies wendet jedoch wiederum denselben Filter auf alle Standardabfragen an, die für das
Event
Modell ausgeführt werden, und ist daher bei einigen der oben beschriebenen Techniken nicht so flexibel.quelle
Dies kann mit einem Zuweisungs-Tag gelöst werden:
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)
quelle
Für alle, die 2020 nach einer Antwort suchen. Das hat bei mir funktioniert.
In Ansichten:
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
In Vorlage:
{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}
Im Pseudocode:
For each in model.child_object|view_filter:filter_arg
Hoffentlich hilft das.
quelle