2010-01-16 9 views
5

Das Problem ist, dass, wenn ich ein TemplateTag in einen Block aufrufen und es mir eine Variable mit dem üblichen Kontext [Varname] = etwas füllt, dann wenn ich diese Variable in eine andere brauchen Block, ich muss das TemplateTag erneut aufrufen. Dies bedeutet für mich zusätzliche DB-Abfragen, was wirklich etwas ist, das ich versuche zu vermeiden.Django Templatetag Bereich zwingt mich, zusätzliche Abfragen zu tun

Dieser TemplateTag wird in einer Basisvorlage genannt, die durch viele andere Vorlagen erweitert wird, so kann ich nicht nur alle Ansichten ändert etwas Kontext passieren, macht es keinen Sinn (WET Prinzip?)

Auch ein Kontextprozessor wäre nicht gut, weil ich nicht für jede Seite auf der Website gerendert werden möchte, auch die nicht auf dieser Vorlage basieren.

Ich dachte über das Schreiben eines TemplateTag, die interne Kontextstrukturen verwenden würde, um die Variable in einen globalen Kontext, setzen, aber ich fühle mich zu schuldig, es zu tun.

Wie würden Sie dieses Problem lösen?

Antwort

0

Versuchen Sie nur, die Anzahl der Datenbankabfragen gering zu halten, oder suchen Sie nach einer cleveren Lösung?

Wenn es ersteres ist, würde ich definitiv mit Caching gehen. Würde das Caching in Ihrem Fall fragmentieren? Wenn nicht, könnten Sie das Caching möglicherweise in den Template-Tag-Code einfügen (vorausgesetzt, es handelt sich nicht um eines von Djangos eigenen Template-Tags, die Sie verwenden)?

+0

Caching hier sieht aus wie ein Schmetterling mit einem Maschinengewehr schießen! –

3

Sie sagten: "Dieses TemplateTag wird in einer Basisvorlage aufgerufen, die um viele andere Vorlagen erweitert wird."

Die Frage ist: Wird dieses Tag innerhalb eines benannten Blocks aufgerufen? Wenn es dann ist, haben Sie ein paar potentielle Probleme.

  1. {% block %} schiebt einen neuen dict auf dem Stapel Kontext und knallt es aus, wenn es die passende erreicht `{% endblock%}‘. Dies bedeutet, dass jeder Kontextwert, der während des Blocks erstellt wurde, beim Blockausstieg im Wesentlichen nicht mehr gültig ist.

  2. Wenn dieser Block von einer anderen Vorlage überschrieben wird, die die Basisvorlage erweitert, ist der Wert möglicherweise überhaupt nicht verfügbar, außer Sie tun eine {{block.super}}, und selbst dann bin ich nicht sicher, ob der Wert für die Vorlage verfügbar ist die Verlängerung machen.

Wenn das Tag nicht aus einem {% block %} dann der Kontextwert genannt ist, sollte auf den gesamten Code zur Verfügung, die es folgt, entweder in der Basisvorlage, jede Vorlagen enthalten und (glaube ich) alle Erweiterung von Vorlagen

Dies ist einer jener Fälle, in denen das Erstellen einer Reihe sorgfältiger Tests Ihnen wahrscheinlich Zeit und Tränen ersparen wird.

Alternativ können Sie, wenn Sie immer auf diesen Wert zugreifen, ihn einfach in eine context processor setzen, damit seine Verfügbarkeit garantiert ist.

Update für Kommentare: OK, Zeit, um die großen Waffen zu bringen!Einer der irritierendsten, seit langem bestehenden Fehler in Django Templates ist, dass Callables (dh Funktionen), die oberste Ebene Kontextwerte sind (im Gegensatz zu Funktionen, die von Kontextwerte sind) werden nicht aufgerufen ! Dieses Ticket ist über 2 Jahre alt und benötigt ca. 10 Zeilen Code, um es zu reparieren. Wir haben mehrere schwere DB-Aufrufe, die wir nur passieren wollen , wenn der Vorlagencache abgelaufen ist. Also wir a) MonkeyPatched die Vorlage _resolve_lookup() Code, um das aufrufbare Problem zu beheben, und dann b) curry Funktionen alle erforderlichen Parameter haben, wenn erforderlich, weil Sie nicht Params zu Funktionen in der Vorlage "Sprache" übergeben können.

+0

Wenn die Vorlage, in der er das Tag aufruft, auch eine andere Vorlage erweitert, hat das Aufrufen eines kontextverändernden Vorlagen-Tags außerhalb eines Blocks tatsächlich keinerlei Auswirkungen auf irgendetwas. Ich vermute, das ist seine Situation. –

+0

Ja, das Aufrufen außerhalb eines Blocks funktioniert nicht. Dies liegt daran, dass ich eine andere Vorlage erweitere. –

2

Ich denke, Sie haben die Einschränkungen in dieser Situation genau beschrieben. Die wartungsfreundlichsten Lösungen werden wahrscheinlich eine Umstrukturierung Ihrer Template-Vererbungskette mit sich bringen, obwohl es schwer zu sagen ist, ohne die Details zu kennen. Können Sie eine neue Vorlage in die Vererbungshierarchie einführen, wahrscheinlich irgendwo in der Nähe der Spitze der Pyramide, so dass sie nur von Vorlagen geerbt wird, die diese Daten benötigen, wobei ein einziger Block die gesamte Region umfasst, in der Sie diese Daten benötigen? Dieser große Block kann dann in kleinere Blöcke unterteilt werden, die von erbenden Vorlagen überschrieben werden. Wenn Sie Ihren TemplateTag am Anfang dieses Blocks aufrufen, haben alle darin enthaltenen Blöcke (einschließlich der Erben von Templates) Zugriff auf die Daten.

Update: Ich kann nicht viel sagen, ohne Ihre Vorlagen zu sehen, aber die Einführung einer neuen Vorlage in der Mitte einer Vererbungskette beinhaltet sehr selten die "Änderung aller Vorlagen" in einer vernünftigen Vererbungsstruktur, mit der es oft gemacht werden kann ändert sich nur zu einer oder zwei anderen Vorlagen. Und ich denke, was ich vorschlage, ist eigentlich kein Hack, es ist einfach ein besseres Design. Wenn Sie in bestimmten Teilen Ihrer Site und nicht in anderen Teilen bestimmte Daten benötigen, sollte eine bestimmte einzelne Vorlage sein, auf die Sie zeigen können und sagen "diese Vorlage stellt die logische Ebene dar, auf der diese Daten eingefügt werden, und umfasst die Teile der Website, auf denen diese Daten benötigt werden. "

+0

Danke carl, Leider sind die beiden Blöcke 1) die linke Seitenleiste, 2) die rechte Seitenleiste. Sie unter einen gemeinsamen Block zu stellen, wäre angesichts des aktuellen Layouts von Templates sehr schwierig und ich möchte nicht alle Templates ändern, nur weil ich eine Variable nicht in zwei Blöcken lesen kann, ich betrachte es als Hack. Danke für die Vorschläge! –

0

kam gerade über diesen Trick von Liviu, Agile Bear (alle Kredit geht zu ihm)

Statt

context['some_var']='some value' 

tun tun

context.dicts[0]['some_var']='some value' 

Kann nicht sein, by-the-Buch- Coding-Practice funktioniert aber gut genug

Verwandte Themen