Search code examples
djangodjango-modelsdjango-templatesdjango-taggit

How to filter posts by tags using django-taggit in django


Currently, I'm still learning with Django and creating my blog using Django 2.2. but somehow there's an error when I using django-taggit.

How to filter the post by tags?

I've read the documentation but there's not fully covered about how to implement this into a real project.

Here's my code:

I've tried several different ways that I'm still searching from StackOverflow but still doesn't have an answer.

The results from /blog/tag/post-tagged is the same from /blog. So how do I filter it from views.py? or perhaps from blog.html?.

So the result of /blog/tag/post-tagged is only from the tagged post.

here's my code:

models.py:

...

from taggit.managers import TaggableManager



"Post Model"
class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    slug = models.SlugField(max_length=100, null=True, blank=True, unique=True)
    title = models.CharField(max_length=200)

    tags = TaggableManager(blank=True)
...

views.py:

def blogIndex(request):
    posts = Post.objects.all().order_by("-created_date")[0:4]
    context = {"posts": posts,}
    return render(request, 'blog.html',  context)



def Tagging(request, slug):

    tags = Tag.objects.filter(slug=slug)
    posts = Post.objects.all().order_by("-tags")

    context = {
        'tags': tags,
        'posts': posts,
    }
    return render(request, 'blog.html', context)

urls.py:

path("tag/<slug:slug>/", views.Tagging, name='tagged'),

my blog.html:

<div id="tags-middle">
   <div class="tags-cloud">
      Tags :
      {% for tag in post.tags.all %}
         <a href="{% url 'tagged' tag.slug %}">{{ tag.name }}</a>
      {% endfor %}
    </div>
</div>

Solution

  • I've solved this issue by filtering the tags from views.py.

    Since I have multiple tags in my posts. so the __in and tags must be in the list.

    Here's my views.py:

    tags = Tag.objects.filter(slug=slug).values_list('name', flat=True)
    posts = Post.objects.filter(tags__name__in=tags)
    

    Basically, as the documentation said that we can filter by using string just like:

    posts = Post.objects.filter(tags__name__in=["Lorem"])
    

    But it only takes one string.

    if I try by using multiple strings like ["Lorem", "Ipsum"] it will show me only a blank page on /blog/tag/lorem.