如何使用标签显示与帖子相关的所有帖子标题

时间:2019-06-27 13:56:07

标签: python django tags filtering

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

我在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>

我的views.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'),

1 个答案:

答案 0 :(得分:0)

  

“ 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,那么您可能实际上并不需要模板过滤器,因为您已经完成了filteringview

说明

../tag/cars/获得包含Poststag

slug = car的列表

在您的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>