Frage

Ich brauche einen gefilterten Abfrage innerhalb einer django Vorlage auszuführen, eine Reihe von Objekten entsprechen Python-Code in einer Ansicht zu erhalten:

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

In meiner Vorlage würde ich tun

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

, aber ich kann einfach nicht scheinen, um herauszufinden, wie FILTER schreiben zu können.

War es hilfreich?

Lösung

Sie können dies nicht tun, die durch Design. Die Django Framework Autoren sollten eine strikte Trennung von Präsentationscode von Datenlogik. Filtering-Modelle Datenlogik und HTML-Ausgabe von Präsentationslogik ist.

So haben Sie mehrere Möglichkeiten. Am einfachsten ist es, die Filterung zu tun, dann das Ergebnis passieren render_to_response. Oder Sie könnten eine Methode in Ihrem Modell schreiben, so dass Sie {% for object in data.filtered_set %} sagen können. Schließlich könnten Sie Ihren eigenen Template-Tag schreiben, obwohl in diesem speziellen Fall, dass ich dagegen raten würde.

Andere Tipps

ich fügen Sie einfach ein zusätzliches Template-Tag wie folgt aus:

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

Ich laufe in dieses Problem auf einer regelmäßigen Basis und verwenden häufig die Lösung „eine Methode hinzufügen“. Allerdings gibt es Fälle, in denen auf jeden Fall „eine Methode hinzufügen“ oder „berechnen sie in der Ansicht“ funktionieren nicht (oder nicht gut). Z.B. wenn Sie Template-Fragmente werden Caching und müssen einige nicht-triviale DB Berechnung es zu produzieren. Sie wollen nicht die DB Arbeit tun, wenn es nötig ist, aber Sie werden nicht wissen, wenn Sie benötigen, bis Sie in der Vorlage Logik sind tief.

Einige andere mögliche Lösungen:

  1. Mit dem {% ausdr als %} Template-Tag unter gefunden http://www.djangosnippets.org/snippets/9/ Der Ausdruck jeder juristischer Python-Ausdruck mit Ihrer Vorlage Kontext als lokalen Bereich ist.

  2. Ändern Sie Ihre Template-Prozessor. Jinja2 ( http://jinja.pocoo.org/2/ ) hat Syntax, die fast identisch ist, die Django Template-Sprache, aber mit voller Python Leistung zur Verfügung. Es ist auch schneller. Sie können diesen Großhandel tun, oder Sie könnten ihre Verwendung beschränken, die Vorlagen Sie arbeiten, aber Djangos „sicherer“ Vorlagen für Designer gepflegt Seiten.

Dies kann mit einer Zuweisung 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)

Die andere Option ist, dass, wenn Sie einen Filter haben, die Sie immer angewandt werden sollen, ein benutzerdefinierte Manager auf dem Modell in Frage, die die Filter auf die Ergebnisse zurück immer gilt.

Ein gutes Beispiel hierfür ist ein Event Modell, bei dem 90% der Abfragen, die Sie auf dem Modell tun werden Sie so etwas wie Event.objects.filter(date__gte=now) wollen, das heißt Sie sind normalerweise in Events interessiert, die kommenden werden. Dies würde wie folgt 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()

Aber auch hier gilt dies den gleichen Filter gegen alle Standardabfragen auf dem Event Modell gemacht und so ist nicht so flexibel einige der oben beschriebenen Techniken.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top