【问题标题】:How to display all titles of posts related to a post using tags如何使用标签显示与帖子相关的所有帖子标题
【发布时间】:2019-11-09 13:41:12
【问题描述】:

我想使用带有标签的 django 过滤器显示相关帖子。 我写了这个过滤器,但是查询集不会用标题过滤。 也许有人可以给我一个提示,如何重写我的过滤器以显示与同一标签相关的所有帖子。

我在 app_tags.py 中的过滤器

@register.filter(name='related_posts')
def related_posts(tag):
    posts = Post.objects.filter(tags__name__in = [tag])
    return posts.title()

我的 HTML:

<div class="containernav">
<div class="mt-3 p-3 bg-white rounded box-shadow  border border-gray">
        <h6 class="border-bottom border-gray pb-2 mb-0">Verwandte Posts</h6>
        <div class="media text-muted pt-3">
            {% load app_tags %}
            <a href="{% url 'post_detail' post.slug  %}">{{ tag | related_posts }}</a>
          </p>
        </div>
      </div>
</div>

我对posts.count 做了同样的事情,而且效果很好。但它不会显示具有相同标签的所有帖子的标题。 在上面的例子中,它说 Querset 没有属性“title”。

我也试过这个:

app_tags.py

@register.filter(name='related_posts')
def related_posts(self):
    return Post.objects.filter(tags__in=self.tags.all())

HTML:

  <div class="mt-3 p-3 bg-white rounded box-shadow  border border-gray">
    <h6 class="border-bottom border-gray pb-2 mb-0">Verwandte Posts</h6>
    <div class="media text-muted pt-3">
        {% load app_tags %}
        {% for post in posts.related_posts %}
        <a href="{% url 'post_detail' post.slug  %}">{{ post.title }}</a>
      </p>
      {% endfor %}
    </div>
  </div>

models.py

 class Post(models.Model):
        title = models.CharField(max_length=200, unique=True)
        slug = models.SlugField(max_length=200, unique=True)
        author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
        updated_on = models.DateTimeField(auto_now= True)
        content = RichTextField(config_name='awesome_ckeditor')
        created_on = models.DateTimeField(auto_now_add=True)
        status = models.IntegerField(choices=STATUS, default=1)
        tags = TaggableManager()

我的 app_tags.py

from blog.models import Post
from django import template
register = template.Library()

@register.filter(name='count_tags_usage')
def count_tags_usage(tag):
    posts = Post.objects.filter(tags__name__in = [tag])
    return posts.count()

@register.filter(name='related_posts')
def related_posts(tag):
    posts = Post.objects.filter(tags__name__in = [tag])
    # iterate over the QuerySet [posts]
    for i in posts:
        return i.title

我的新 Html 配置:

<div class="containernav">
<div class="mt-3 p-3 bg-white rounded box-shadow  border border-gray">
        <h6 class="border-bottom border-gray pb-2 mb-0">Verwandte Posts</h6>
        <div class="media text-muted pt-3">
            {% for tag in post.tags.all %}
            {% load app_tags %}
            <a href="{% url 'post_detail' post.slug  %}">{{ tag | related_posts }}</a>
          {% endfor %}
          </p>
        </div>
      </div>
</div>

我的意见.py

from django.views import generic
from .models import Post
from django.shortcuts import render
from django.db.models import Q
from django.shortcuts import redirect


class PostList(generic.ListView):
    model = Post
    template_name = 'index.html'
    paginate_by = 15


class PostDetail(generic.DetailView):
    model = Post
    template_name = 'post_detail.html'


def tag(request, slug):
    posts = Post.objects.filter(tags__slug=slug)
    return render(request, 'index.html', {"post_list": posts, "slug": tag})


def about(request):
    return render(request, 'about.html', {})

##def verzeichnis(request):
   ##return render(request, 'verzeichnis.html', {})

def searchposts(request):
    if request.method == 'GET':
        query= request.GET.get('q')

        submitbutton= request.GET.get('submit')

        if len(query) == 0:
                return redirect( 'https://www.code-reminder.com/')

        if query is not None:
            lookups= Q(title__icontains=query) | Q(content__icontains=query)

            results= Post.objects.filter(lookups).distinct()

            context={'results': results,
                     'submitbutton': submitbutton}

            return render(request, 'search.html', context)


        else:
            return render(request, 'search.html')

    else:
        return render(request, 'search.html')

我的 urls.py

from . import views
from django.urls import path
from django.urls import include
from django.views.generic.base import RedirectView





urlpatterns = [
    path('', views.PostList.as_view(), name='home'),
    path('about', views.about, name='about'),
   ##path('verzeichnis', views.verzeichnis, name='verzeichnis'),
    path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
    path("tag/<slug:slug>/", views.tag, name='tag'),

【问题讨论】:

    标签: python django tags filtering


    【解决方案1】:

    'QuerySet' 对象没有属性'title'

    您收到的错误消息是由于您尝试执行[queryset].title 而导致的。

    Django 将 QuerySet 作为对象列表返回。

    所以你可以这样做

    def related_posts(tag):
        posts = Post.objects.filter(tags__name__in = [tag]).distinct()
        # iterate over the QuerySet [posts]
        for i in posts:
            return i.title
    

    更新

    根据我的观察,如果 views.py 实际上呈现了您希望完成此操作的实际 template,那么您可能不需要模板过滤器,因为您已经在 view 上完成了 filtering

    为了说明

    ../tag/cars/ 获取包含tagslug = carPosts 列表

    在你的view这里

    def tag(request, slug):
        # returns posts with tags__slug = slug
        posts = Post.objects.filter(tags__slug=slug)
        return render(request, 'index.html', {"post_list": posts, "slug": tag})
    

    那么你的template就变成了

    <div class="media text-muted pt-3">
                {% for post in post_list %}
                <a href="{% url 'post_detail' post.slug  %}">{{ post.title }}</a>
                {% endfor %}
    

    PostDetail 视图的更新

    所以我们现在实际上可以放弃自定义模板过滤器,并将过滤后的 related_posts 作为上下文传递给 PostDetail

    PostDetail 视图变为

    class PostDetail(generic.DetailView):
        model = Post
        template_name = 'post_detail.html'
    
        def get_context_data(self, **kwargs):
            context = super(PostDetail, self).get_context_data(**kwargs)
            slug = self.kwargs['slug']
            main_post = Post.objects.get(slug=slug)
            # get all related_post and exclude the main post, makes sense that way
            related_posts = Post.objects.filter(tags__name__in=list(main_post.tags.all())).distinct().exclude(slug=slug)
            # add related_posts to the context
            context['related_posts'] = related_posts
            return context
    

    然后将template更新为

     <div class="containernav">
    <div class="mt-3 p-3 bg-white rounded box-shadow  border border-gray">
            <h6 class="border-bottom border-gray pb-2 mb-0">Verwandte Posts</h6>
            <div class="media text-muted pt-3">
                {% for posts in related_posts %}
                <a href="{% url 'post_detail' posts.slug  %}">{{ posts.title }}</a>
              {% endfor %}
            </div>
          </div>
    </div>
    

    【讨论】:

    • 哦,忘了。我以前也用我的搜索字段这样做过。谢谢你的建议。现在,由于某种原因,我得到了 3 次相同的标题。它现在看到它有 3 个相关的帖子,但它发布了 3 次自己的标题。那会是什么?
    • 我只看到它发布了3次自己的标题,因为帖子有3个标签。它没有看到与标签的关系。
    • @DobUro 如果问的不是太多,我可以看看你的models.pyapp_tags.py
    • 我添加了我的 models.py 和我的 app_tags.py。我将标题定义为唯一
    • @DobUro 刚刚更新了我的答案。将 posts = Post.objects.filter(tags__name__in = [tag]) 更改为 posts = Post.objects.filter(tags__name__in = [tag]).distinct() 并告诉我进展如何
    猜你喜欢
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 2014-06-26
    • 2014-12-22
    • 2016-04-05
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多