2017-06-08 8 views
0

Ich versuche, eine Blog-App zu erstellen, die Beiträge hat und jeder Beitrag Titel, Datum, Link und Tags hat.Wie durchläuft ich ein ManyToManyField im django-jinja-Projekt?

Das ist mein models.py

# models.py 
from django.db import models 

class Tag(models.Model): 
    name = models.CharField(max_length=20) 

    def __str__(self): 
     return self.name 

    class Meta: 
     ordering = ('name',) 

class Post(models.Model): 
    title = models.CharField(max_length=300) 
    date = models.DateTimeField() 
    link = models.URLField() 
    tags = models.ManyToManyField(Tag) 

    def __str__(self): 
     return self.title 

    @property 
    def tags_name(self): 
     return [x.name for x in self.tags] 

    class Meta: 
     ordering = ('date',) 

Dieses

mein views.py ist
# views.py 
from django.conf.urls import url, include 
from django.views.generic import ListView 
from blog.models import Post 

urlpatterns = [ 
    url(r'^$', ListView.as_view(queryset=Post.objects.all().order_by("-date"), template_name="blog/blog_list.html")), 
] 

Das ist mein blog_list.html

<!-- blog_list.html --> 
{% extends "mysite/layout.html" %} 

{% block content %} 
    <h1>my blog posts</h1> 
    <ul> 
    {% for post in object_list %} 
     <li><span class="title"><a href="{{ post.link }}">{{ post.title }}</a></span></li> 
     <p>{{ post.date|date:"d-m-Y" }}</p> 
    {% endfor %} 
    </ul> 
{% endblock %} 

{% block sidebar %} 
    <h4 id="sidenav">tags</h4> 
    {% for post in object_list %} 
    <ul> 
     <!-- I want to show the tags here --> 
    </ul> 
    {% endfor %} 
{% endblock %} 

Im blog_list.html, I Ich zeige alle Post-Details und auf der Seitenleiste, ich möchte alle Tags aus allen verfügbaren Blog-Posts zeigen. Da post.tags ManyToManyField ist, wie kann ich es durchlaufen?

+0

Haben Sie versucht, '' '{% für Tag in post.tags.all()%}' ''? Innerhalb dieser for-Schleife sollte es möglich sein, auf Tags als '' '{{tag}}' '' zuzugreifen. –

+1

@ISOmetric Ich meine du meinst '{% für tag in post.tags.all%} {{tag}} {% endfor%}' die '()' sind nicht erlaubt! – hansTheFranz

+0

@hansTheFranz ja, ich glaube du hast Recht, mein Fehler. –

Antwort

0

Sie wollen .all in der Vorlage verwenden, um alle Elemente in der Beziehung zu erhalten:

{% for tag in post.tags.all %} 
    {{ tag }} 
{% endfor %} 

Dank @hansTheFranz für meine Konsole Problem zu korrigieren.

In Bezug auf nicht wiederholende Tags wäre dies mit dem aktuellen Kontext sehr schwierig. Vielleicht möchten Sie sich stattdessen die Posts in Ihrer View ansehen und dort die Tags extrahieren, wo Sie mehr Möglichkeiten haben, nach Duplikaten zu suchen. Etwas wie folgt aus:

def tags(request): 
    posts = Post.objects.all() 
    tag_list = [] 
    for post in posts: 
     tags = post.tags.all() 
     for tag in tag: 
      if not (tag in tag_list): 
       tag_list.append(tag) 
    context_dict = { "tags": tag_list, "posts": posts } 
    return render(request, 'blog/blog_list.html', context_dict) 

urlpatterns = [ 
    url(r'^$', tags, name="tags"), 
] 

Und dann Ihre Vorlage ändern, um mehr zu sein wie:

{% block sidebar %} 
    <h4 id="sidenav">tags</h4> 
    <ul> 
     {% for tag in tags %} 
     <li>{{ tag }}</li> 
     {% endfor %} 
    </ul> 
{% endblock %} 

Zusätzlich statt object_list verweisen Sie jetzt die Liste der Beiträge Referenzierung posts zugreifen können, weil wir definiert haben die Liste der Beiträge als solche in unserem Kontextwörterbuch, das an die Vorlage übergeben wird.

Ich fürchte, ich habe das nicht getestet und es kann nicht sehr effizient sein, aber grob gesprochen sollte es funktionieren. Ein Dozent an meiner Universität schrieb dieses Buch: http://www.tangowithdjango.com/book17/, was mehr zu einem Stil des Schreibens von Ansichten ermutigt, wie ich es getan habe: getrennt von den URLs. Wenn irgendetwas, was ich getan habe, unklar oder gegensätzlich erscheint, sollten Sie sich das Buch ansehen und nachsehen, ob etwas mehr Sinn ergibt.

Verwandte Themen