Как отобразить все заголовки постов, связанных с постом, используя теги - PullRequest
0 голосов
/ 27 июня 2019

Я хочу отображать похожие сообщения, используя фильтр 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()

my 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>

My 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')

Мои URL.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 голосов
/ 27 июня 2019

Объект '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

UPDATE

По моим наблюдениям, если views.py фактически отображает фактический template там, где вы хотите это сделать, тогда вам может не понадобиться фильтр шаблонов, поскольку вы уже сделали filtering на view

Для иллюстрации

../tag/cars/ получает список Posts, который содержит tag с 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...