2009-01-19 4 views
57

Django-Vorlagen bieten das integrierte Tag cycle zum Wechseln zwischen mehreren Werten an verschiedenen Stellen in einer Vorlage (oder für eine Schleife in einer Vorlage), aber dieses Tag wird nicht zurückgesetzt wird in einem Bereich außerhalb der cycle s-Definition zugegriffen. Dh, wenn Sie zwei oder mehr Listen in Ihrer Vorlage haben, die Zeilen von denen Sie einige CSS-Definitionen odd und even verwenden möchten, wird die erste Zeile einer Liste, wo die letzte links aus, nicht mit einem frische Iteration aus der Auswahl (odd und even)Alternate Row Coloring in Django-Vorlage mit mehr als einem Satz von Zeilen

zB in den folgenden Code, wenn der erste Blog eine ungerade Anzahl von Einträgen hat, dann ist der erste Eintrag in einem zweiten Blog als even beginnen wird, wenn ich es will Beginnen Sie bei odd.

{% for blog in blogs %} 
    {% for entry in blog.entries %} 
    <div class="{% cycle 'odd' 'even' %}" id="{{entry.id}}"> 
     {{entry.text}} 
    </div> 
    {% endfor %} 
{% endfor %} 

Ich habe versucht, die Beseitigung dies mit dem resetcycle Tag Patchen hier angeboten:

Django ticket: Cycle tag should reset after it steps out of scope

ohne Erfolg. (Der Code funktionierte nicht für mich.)

Ich habe auch versucht, meine innere Schleife in ein benutzerdefiniertes Tag zu bewegen, aber das hat auch nicht funktioniert, vielleicht weil der Kompilier-/Render-Zyklus die Schleife zurück in den äußeren bewegt Schleife? (Unabhängig davon, warum es für mich nicht funktionierte.)

Wie kann ich diese einfache Aufgabe erfüllen? Ich würde es vorziehen, keine Datenstruktur in meiner Sicht mit diesen Informationen vorkompiliert zu erstellen; das scheint unnötig. Danke im Voraus.

Antwort

109

Die einfachste Abhilfe (bis der resetcycle Patch und angewandt werden behoben wird) ist die integrierte „divisibleby“ Filter mit forloop.counter zu verwenden:

{% for entry in blog.entries %} 
    <div class="{% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}" id="{{ entry.id }}"> 
    {{ entry.text }} 
    </div> 
{% endfor %} 

Etwas ausführlicher, aber nicht schwer zu verstehen und es funktioniert super.

+26

Man kann das auch etwas kürzer schreiben (zumindest in Django 1.3): '{{forloop.counter | divisibleby: 2 | yesno:" even, odd "} } ' – Michael

+1

Schöne Verbesserung, Michael!Ich habe den Yesno-Filter nie wirklich benutzt, aber ich denke, ich habe eine Menge If/Elen in meinen Vorlagen, die auf diese Weise verkürzt werden könnten. –

1

Die einfachste Antwort könnte sein: "Gib auf und benutze jQuery." Wenn das akzeptabel ist, ist es wahrscheinlich einfacher als mit Djangos Vorlagen über etwas so Einfaches zu kämpfen.

+0

Das ist, was ich tue, aber da war ich Mit jQuery sowieso, es war ziemlich trivial. –

2

Aufgeben und verwenden Jinja2 Template System

ich auf django Template-Sprache gab, ist es sehr beschränkt ist, was man damit machen kann. Jinja2 verwendet dieselbe Syntax wie die Django-Vorlage, fügt jedoch viele Verbesserungen hinzu.

EDIT/NOTE (Ich weiß, es wie ein großer Schalter klingt für nur ein kleines Problem, aber in Wirklichkeit Ich wette, Sie sich immer finden die Standard-Template-System in django kämpfen, so ist es wirklich sinnvoll ist und ich es glauben wird auf lange Sicht produktiver.)

Sie können lesen this article written by its author, obwohl es technisch ist, erwähnt er das Problem der {% Zyklus%} Tag in Django.

Jinja keinen Zyklus-Tag hat, hat es eine Zyklusmethode auf der Schleife:

{% for user in users %} 
    <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li> 
{% endfor %} 

Ein großer Vorteil der Jinja2 ist, dass es Sie Logik für die Präsentation verwenden können, also, wenn Sie eine Liste der Bilder, können Sie sie in einer Tabelle setzen, weil Sie alle N Elemente eine neue Zeile in einer Tabelle beginnen können, finden Sie zum Beispiel tun können:

{% if loop.index is divisibleby(5) %} 
    </tr> 
    {% if not loop.last %} 
    <tr> 
    {% endif %} 
{% endif %} 

Sie auch mathematische Ausdrücke verwenden:

{% if x > 10 %} 

und Sie können Ihre Python-Funktionen zugreifen direkt (aber einige Setup erforderlich sind, um festzulegen, welche Funktionen für die Vorlage ausgesetzt werden sollen)

{% for item in normal_python_function_that_returns_a_query_or_a_list() %} 

auch Setvariablen ..

{% set variable_name = function_that_returns_an_object_or_something() %} 
+2

Das ist eine große Umstellung (mit einigen größeren Komplikationen, wie Drittanbieter- oder Contrib-Apps) für solch ein kleines Problem. -1 –

+3

Guter Punkt zu erziehen. Die Sache ist, ich wette, dass die Leute immer wieder mit dem Django-Template-System kämpfen, es ist nicht nur dieses kleine Problem oder das, es ist ein Haufen Ärger. – hasen

+0

Vielen Dank für Ihren Vorschlag und Artikel; Ich habe mich durch Djangos Herangehensweise an Templating und genervt von seinen Fehlern eingeschränkt gefühlt. Aber Djangos süßer Gesamteindruck. –

-5

Es gibt eine Möglichkeit, es serverseitig mit einem Iterator zu tun, der keine gleichzeitige Kopie aller Einträge beibehält:

import itertools 
return render_to_response('template.html', 
    { 
    "flattened_entries": itertools.chain(*(blog.entries for blog in blogs)), 
    }) 
+0

Wie löst das das Problem des OP? Es scheint, dass dies nur eine andere Möglichkeit ist, ein falsches Verhalten zu liefern (alternierende Zeilenfarben, die nicht zwischen Blogposts zurückgesetzt werden). -1 –

+0

Du hast recht, ich habe sein Problem in umgekehrter Richtung verstanden – orip

2

Ich lande damit, mit dem forloop.counter0 - Es funktioniert super!

{% for product in products %} 

    {% if forloop.counter0|divisibleby:4 %}<div class="clear"></div>{% endif %} 

    <div class="product {% if forloop.counter0|divisibleby:4 %}col{% else %}col20{% endif %}"> 
     Lorem Ipsum is simply dummy text 
    </div> 

{% endfor %} 
Verwandte Themen