如何在django-jinja项目中迭代ManyToManyField?

时间:2017-06-08 10:57:38

标签: python django django-models django-templates jinja2

我正在尝试创建一个包含帖子的博客应用,每个帖子都有标题,日期,链接和标签。

这是我的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',)

这是我的views.py

# 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")),
]

这是我的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 %}

在blog_list.html中,我显示了所有帖子详细信息,在侧栏上,我想显示所有可用博客帖子中的所有标签。由于post.tags是ManyToManyField,我如何迭代它呢?

1 个答案:

答案 0 :(得分:0)

您希望在模板中使用.all来获取关系中的所有元素:

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

感谢@hansTheFranz纠正我的支架问题。

关于不重复标记,对于当前上下文来说这将是非常困难的。您可能需要查看在视图中获取帖子并在那里提取标签,您可以更自由地检查重复项。像这样:

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"),
]

然后将模板更改为:

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

此外,您现在可以通过引用object_list来访问帖子列表,而不是引用posts,因为我们已经在我们的上下文字典中定义了帖子列表,该列表正在传递给模板。

我担心我没有对此进行测试,但可能效率不高,但粗略地说它应该可行。我大学的一位讲师写了这本书:http://www.tangowithdjango.com/book17/,它鼓励我更多地写一种风格的写作方式:与URL分开。如果我做的任何事情看起来不清楚或相反,你可能想看看这本书,看看是否有更多的意义。