django-taggit similar_objects() 使い方

similar_objects() を使い方

filter を含めない例)

http://django.zone/blog/posts/using-django-taggit/

テンプレートで

—-

{% if post.tags.similar_objects %}
    Similar:
    {% for s in post.tags.similar_objects|slice:":4" %}
        <a href="{{ s.get_absolute_url }}">{{ s.title }}</a>
    {% if not forloop.last %}, {% endif %}
    {% endfor %}
{% endif %}

—-

これだと filter できないため、post に published == Draft が含まれてします。

* views.detail_view()で以下にしてもダメ(tagsのrelatedでPostを取得するから)

—-

post = get_object_or_404(Post, slug=post,
                         status='published',
                         publish__year=year,
                         publish__month=month,
                         publish__day=day)
return render(request,
              'blog/post/detail.html',
              {'post': post,
               ...})

—-

2) filter を含めたい場合

views.py

—-

def post_detail(request, year, month, day, post):


#another_similar_posts = Post.published.filter(id__in=post.tags.similar_objects()) という使い方はできないので以下
another_similar_posts = []
for s in post.tags.similar_objects()[:4]:
    if s.status == 'published':
        another_similar_posts.append(s)

return render(request,
              'blog/post/detail.html',
              {'post': post,
              …
               'another_similar_posts': another_similar_posts})

—-

template.html

—-

...
Similar:
{% for s in another_similar_posts %}
    <a href="{{ s.get_absolute_url }}">{{ s.title }}</a>
    {% if not forloop.last %}, {% endif %}
{% endfor %}

—-

 

3)いっそ similar_objects を使わないなら

views.py

—-

def post_detail(request, year, month, day, post):
...
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags'))\
                    .order_by('-same_tags', '-publish')[:4]

—-

template.html

—-

<h2>Similar posts</h2>
{% for post in similar_posts %}
    <p>
        <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
    </p>
{% empty %}
    There are no similar posts yet.
{% endfor %}

—-

Leave a Reply

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です