Reputation: 3023
I want to know how to make category page view using class based view I know how to make this in function based view by using get_object_or_404(category, slug=None)
But I am confused how to do this it in class based views. I tried to google this but I am unable to find anything related to this in class view.
I know I could have used function based view but I have used class based view in whole project so I thought to use them here as well
my code
models.py
from django.db import models
from django.utils import timezone
from slugger import AutoSlugField
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Category(models.Model):
title = models.CharField(max_length= 60)
slug = AutoSlugField(populate_from='title')
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children',on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
class Meta:
verbose_name_plural = 'categories'
def __unicode__(self):
return self.title
def __str__(self):
return self.title
def get_absolute_url(self, slug=None):
return reverse("posts-detail", kwargs={"slug": self.slug})
class Post(models.Model):
title = models.CharField(max_length=120)
slug = AutoSlugField(populate_from='title')
image = models.ImageField(
upload_to=upload_location,
null=True,
blank=True,
)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='postcategory')
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ['-date_posted']
def __str__(self):
return self.title
def get_absolute_url(self, slug=None):
return reverse("posts-detail", kwargs={"slug": self.slug})
urls.py
from django.urls import path
from django.urls import path, include
from .views import PostView, PostDetailView,LatestPostView, CategoryPostListView
urlpatterns = [
path('', PostView.as_view(), name='posts-home'),
path('latest/', LatestPostView.as_view(), name='posts-latest'),
path('<slug>', PostDetailView.as_view(), name='posts-detail'),
path('category/<slug>', CategoryPostListView.as_view(), name='category-detail'),
]
views.py
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.shortcuts import redirect, render,get_object_or_404
#class based view
from django.views.generic import ListView, DetailView
from .models import Post, Category
class PostView(ListView):
template_name = 'posts/home.html'
model = Category
context_object_name = 'all_categs'
def get_queryset(self):
if self.request.user.is_authenticated:
return Category.objects.all()
else:
return Category.objects.all().exclude(title__iexact = 'Featured')[:6]
def get_context_data(self):
if not self.request.user.is_authenticated:
fcategory = Category.objects.get(title__iexact = 'Featured')
context = super(PostView, self).get_context_data()
context['latest_posts'] = Post.objects.exclude(category= fcategory).order_by('-date_posted')[0:6]
context['featured_posts'] = Post.objects.all().filter(category= fcategory).order_by('-date_posted')[0:6]
return context
else:
fcategory = Category.objects.get(title__iexact = 'Featured')
context = super(PostView, self).get_context_data()
context['latest_posts'] = Post.objects.order_by('-date_posted')
context['featured_posts'] = Post.objects.all().filter(category= fcategory).order_by('-date_posted')[0:6]
return context
# def get_success_url(self):
# return reverse('home') #add your path
class LatestPostView(LoginRequiredMixin, ListView):
template_name = 'posts/post_latest.html'
model = Post
context_object_name = 'Posts'
ordering = ['-date_posted']
paginate_by = 6
class PostDetailView(LoginRequiredMixin,DetailView):
model = Post
template_name = 'posts/post_detail.html'
class CategoryPostListView(LoginRequiredMixin, ListView):
model = Category
template_name = 'posts/category_detail.html'
# def get_queryset(self):
# category = get_object_or_404(Category, )
I thought of defining get_queryset
inside CategoryPostListView
. But I am not sure if it will work or not.
Upvotes: 0
Views: 184
Reputation: 3600
Yes. you can use get_object_or_404
in class-based views. just add this to your CategoryPostListView
:
class CategoryPostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'posts/category_detail.html'
def get_queryset(self):
category = get_object_or_404(Category, slug=self.kwargs['slug'])
# do another stuffs here
return Post.objects.filter(category=category)
for more information you can read dynamic filtering in class-based views in django official site
Upvotes: 0
Reputation: 308779
Firstly, if you are using ListView and want to display a list of posts, then you need model = Post
.
Next, you can call get_object_or_404
in the get_queryset method. You can access slug
from the URL with `self.kwargs['slug'].
Finally, you can filter the queryset to only return posts in that category.
class CategoryPostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'posts/category_detail.html'
def get_queryset(self):
category = get_object_or_404(Category, slug=self.kwargs['slug'])
return super(CategoryPostListView, self).get_queryset().filter(category=category)
Note that your problem is very similar to the dynamic filtering section in the docs.
Upvotes: 1