dynamische Navigation mit Unterpunkten in Django

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Donnerstag 17. Januar 2008, 16:53

heo

ich bin gerade am Überlegen wie man eine dynamisch generierte Navigation (aus einer mysql Datenbank) mit Django erstellt.

Bisher siehts so aus: Artikel werden nach Themen und "Unterthemen" gruppiert gespeichert.

die navigation sollte so aussehen :

-Thema1
-Thema2
-Thema3

wenn zb Thema2 ausgewählt wird sollte sich die Struktur wie folgt ändern

-Thema1
-Thema2
-subthema2.1
-subthema2.2
-Thema3

usw...

leider hab ich zur Zeit keinen Plan wie ich das realisiern könnte (mit den Unterpunkten) da ja die Django Template Engine kein Vergleiche in einem Template zulässt.

Würde mich über Anregungen sehr freuen ;-)

mfg[/list]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 17. Januar 2008, 19:24

Leider bietet die django Template Engline keine Rekursion, siehe: http://www.python-forum.de/topic-9655.html

In PyLucid nutzte ich ein einfaches Parend-ID Tree und generiere mein Tree-Menü im Skript. Ist natürlich doof, aber erstmal eine funktionierende Lösung.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Donnerstag 17. Januar 2008, 20:36

hm ja das menu auf http://www.pylucid.org/ funktioniert prinzipiell so wie ich das auch gerne hätte.

wäre es evtl möglich dass du die relevanten Codeteile posten könntest, da ich zur Zeit nicht weiß, was du mit Parend-ID Tree meinst?

Meine Seite wird auch unter der GPL stehen (jaja Linux und seine Tücken ;-)) und du wirst für den Beitrag sicher erwähnt !
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 17. Januar 2008, 21:29

Ich als Webuser finde Menüs die ich erst anklicken muss und einen ganzen HTTP-Transmit-Zyklus auf das "aufklappen" warten muss einfach nur lästig. AJAX wäre das mindeste, optimal wäre etwas was ohne solche Menüs auskommt. Überfrachtete Menüs sind aus der Usability-Sicht auch nicht optimal.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Freitag 18. Januar 2008, 09:10

naja auf der HP werden viele Infos (zum Thema GLobal Warming) online gestellt (Artikel wie gesagt in Themen wie Allgemeines usw gruppiert....)
und irgendwie muss ich auch auf die einzelnen Artikel zum Thema Allgemeines zugreifen...

Ich sehe zurzeit kein andere Möglichkeit als ein vorher angeführtes Menu, da ich zuerst eine einfache(ohne javascript/ajax) variante erstellen will und auch unter Zeitdruck stehe...

aber für neuerer Versionen danke für den Tip.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Freitag 18. Januar 2008, 13:29

jens hat geschrieben:Leider bietet die django Template Engline keine Rekursion, siehe: http://www.python-forum.de/topic-9655.html
Klar geht ne Rekursion :)
tag
template

Ich gestehe: Nicht perfekt, aber mir gefällts :)
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 18. Januar 2008, 17:38

apollo13 hat geschrieben:Klar geht ne Rekursion :)
tag
template
Das sieht interessant aus! Muß ich mal versuchen nach zu bauen! Danke für den Link.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Samstag 19. Januar 2008, 10:35

Wenn ich's richtig verstehe, hast du so etwas:

Code: Alles auswählen

class Topic(models.Model):
    name = models.CharField()

class Subtopic(models.Model):
    name = models.CharField()
    topic = models.ForeignKey(Topic, related_name='subtopics')

class Article(models.Model):
    topic = models.ForeignKey(Topic)
    subtopic = models.ForeignKey(Subtopic)
Nun kannst du doch auf seiner Seite (ich nehme an, `topic` und `article` sind im Kontext) deine Navigation direkt anzeigen:

Code: Alles auswählen

<ul>
{% for topic in topic_list %}
    <li class="{% if topic|contains_article:article %}open{% else %}closed{% endif %}">{{topic.name}}
        <ul>
            {% for subtopic in topic.subtopics %}
                <li class="{% if subtopic|contains_article:article %}selected{% endif %}">{{subtopic.name}}</li>
            {% endfor %}
        </ul>
    </li>
{% endfor %}
</ul>
Aus den einzelnen Einträge willst du jetzt wahrscheinlich noch Hyperlinks machen, damit ein Klick auf ein Topic oder Subtopic die zugehörigen Artikel listet. Auf- und Zuklappen würde ich mit CSS bzw. JavaScript realisieren und nicht jedes Mal eine neue Seite laden. Wenn ein Artikel angezeigt wird, wird das entsprechende Thema geöffnet und das Unterthema geeignet hervorgehoben.

Die Tests, um die richtige CSS-Klasse zu bestimmen, sind wahrscheinlich so komplex, das man sie nicht direkt mit Django-Mittels im Template ausdrücken kann und daher nutze ich hier einen Filter (was einfacher ist als ein Tag):

Code: Alles auswählen

def contains_article(value, article):
    if isinstance(value, Topic):
        return article and article.topic == value
    else:
        return article and article.subtopic == value and article.topic == value.topic
Stefan
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Samstag 19. Januar 2008, 14:01

ja fast genauso sieht die Situation bei mir aus.

nun aber zum Verständnis (hab noch nie mit django template tags bzw filtern gearbeitet) :

Code: Alles auswählen

<ul>
{% for topic in topic_list %}
    <li class="{% if topic|contains_article:article %}open{% else %}closed{% endif %}">{{topic.name}}
        <ul>
            {% for subtopic in topic.subtopics %}
                <li class="{% if subtopic|contains_article:article %}selected{% endif %}">{{subtopic.name}}</li>
            {% endfor %}
        </ul>
    </li>
{% endfor %}
</ul>
das class="{% if topic|contains_article:article %}open{% else %}closed{% endif %} in Zeile 3 bewirkt, dass falls sich der angeforderte article in topic befindet die css Klasse open benutzt, sonst closed?

Danke für diesen Tip, werd mich gleich mal das Kapitel Extending the Template Engine im Django Book lesen!

mfg
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Samstag 19. Januar 2008, 14:20

d3f3nd3r hat geschrieben:das class="{% if topic|contains_article:article %}open{% else %}closed{% endif %} in Zeile 3 bewirkt, dass falls sich der angeforderte article in topic befindet die css Klasse open benutzt, sonst closed?
Ja.

Ich würde es eigentlich mehr einen Hack nennen, da ich in Django (im Gegensatz zu Jinja - wieso heißt das eigentlich wie eine Stadt in Uganda ;) keine komplexen Abfragen im "if" machen kann.

Stefan
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Sonntag 20. Januar 2008, 15:11

ja du lagerst den if vergleich vom template in python aus, hab ich das richtig verstanden?

und wie man mit css dinge verstecken kann usw muss ich mir mal anschaun ;-)
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Montag 21. Januar 2008, 21:19

eine sache muss ich leider noch fragen (ja ist mir auch ein wenig unangenehm) aber ich hab jetzt die django doku zu dem thema durchgesehn, hab aber trotzdem keine ahnung wie ich das mit den filtern hinbiegen kann...

also ich hab jetzt mit startapp eine neue app mit namen templatetags erstellt
im website root verzeichnis, darin befindet sich die __init__.py und c_tags.py

c_tags.py

Code: Alles auswählen

from django import template

register = template.Library()

def contains_article(value, article):
    if isinstance(value, Topic):
        return article and article.topic == value
    else:
        return article and article.subtopic == value 
in der settings.py steht folgendes

Code: Alles auswählen

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'comenius_py.db',
    'comenius_py.engine',
    'comenius_py.templatetags',
)
im template lade ich mit {% load c_tags %} die filter aus c_tags.py
aber die template engine sucht nur im /var/lib/python-support/python2.4/django/template/defaulttags.py verzeichnis....

wie kann ich website/templatags zu den durchsuchten modulen hinzufügen??

mfg
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Montag 21. Januar 2008, 22:52

@d3f3nd3r:
Die Struktur wäre folgende:
<projekt_dir>/<deine_app>/templatetags/c_tags.py

Dann sicherstellen, dass <deine_app> in INSTALLED_APPS ist und dann erst geht {% load c_tags %}
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Montag 21. Januar 2008, 23:25

sma hat geschrieben:wieso heißt das eigentlich wie eine Stadt in Uganda ;) keine komplexen Abfragen im "if" machen kann.
Jinja FAQ hat geschrieben:Why the Name?

The name Jinja was chosen because it's the name of a Japanese temple and temple and template share a similar pronunciation.
TUFKAB – the user formerly known as blackbird
d3f3nd3r
User
Beiträge: 40
Registriert: Montag 19. November 2007, 20:17

Dienstag 22. Januar 2008, 12:37

ja danke das für den tip mit den filtern.
Antworten