Home > Net >  not good template loaded in Django generic list view when using filter
not good template loaded in Django generic list view when using filter

Time:09-20

I have a strange behavior im my generic views. Below is the classic FBV scheme I want to reproduce in a CBV

My FBV

def post_list(request, tag_name=None):
    
    if tag_name:
        # filter post according to tag name if provided
        posts = Post.objects.filter(tag__tag_name=tag_name)
    else:
        posts = Post.objects.all()
    
    context = {"posts": posts}
    
    return render(request, "blog/post_list.html", context)
    

  def post_detail(request, post_id):
    
    post = Post.objects.get(pk=post_id)
    
    context = {"post": post}
    
    return render(request, "blog/post_detail.html", context)

My CBV

class PostList(ListView):
    model = Post
    context_object_name = "post_list"
    template_name = "blog/post_list.html"
    
    def get_queryset(self):
    
        if "tag_name" in self.kwargs:
            return Post.objects.filter(tag__tag_name=self.kwargs["tag_name"])
        else:
            return Post.objects.all()
            
class PostDetail(DetailView):
    model = Post
    context_object_name = "post_detail"
    template_name = "blog/post_detail.html"

Here are my models

from django.db import models

# Create your models here.
class Tag(models.Model):
    tag_name = models.CharField(max_length=100)
    
    def __str__(self):
        return self.tag_name

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    tag = models.ManyToManyField(Tag, blank=True)
    
    def __str__(self):
        return self.title

And here my urls

from django.urls import path
from .views import PostList, PostDetail

urlpatterns = [
    path("", PostList.as_view(), name="blog-index"),
    path("<tag_name>", PostList.as_view(), name="blog-index"),
    path("<int:pk>", PostDetail.as_view(), name="post-detail")
]

As you can see I want to use the same generic view for the list of my posts with an optional tag provided in url. It is well filtering my articles when I provide a url with a tag, something like this .../blog/my_tag but problem is that the DetailView process does not work anymore. It loads my blog/post_list.html with empty list always instead of my blog/detail_post.html template. The DetailView process works well when I remove the process to filter with tag.

I hope this is clear enough. What I am doing wrong ?

CodePudding user response:

The url pattern is the problem here: All your detail view request are getting matched with Second path i.e: path("<tag_name>", PostList.as_view(), name="blog-index"), try to provide a path pattern with converters that they match as you want in your application.The sequence matters here as first match is first served.

Instead of this:

urlpatterns = [
    path("", PostList.as_view(), name="blog-index"),
    path("<tag_name>", PostList.as_view(), name="blog-index"),
    path("<int:pk>", PostDetail.as_view(), name="post-detail")
]

You can differentiate by some prefixes and path converters so that they match the exact case as you want for example:

urlpatterns = [
    path('postlist/', PostList.as_view(),name='blog-index'),
    path('postlist/<str:tag_name>/', PostList.as_view(),name='blog-index-tag'),
    path('postdetail/<int:pk>/', PostDetail.as_view(),name='post-detail'),
   
]
  • Related