如何使用基于类的视图制作类别视图以列出Django中具有相关类别的所有帖子

时间:2019-03-11 15:27:10

标签: python django

我想知道如何使用基于类的视图制作类别页面视图,我知道如何通过使用get_object_or_404(category, slug=None)在基于函数的视图中制作类别页面视图,但是我对如何在基于类的视图中做到这一点感到困惑。我试图用谷歌搜索,但是在类视图中找不到与此相关的任何内容。

我知道我可以使用基于函数的视图,但是我在整个项目中都使用了基于类的视图,所以我也想在这里使用它们。

我的代码

  

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, )

我想到了在get_queryset内定义CategoryPostListView。但是我不确定它是否会起作用。

2 个答案:

答案 0 :(得分:1)

首先,如果您正在使用ListView并要显示帖子列表,则需要model = Post

接下来,您可以在get_queryset方法中调用get_object_or_404。您可以使用`self.kwargs ['slug']从URL访问slug

最后,您可以过滤查询集以仅返回该类别中的帖子。

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)

请注意,您的问题与文档中的dynamic filtering section非常相似。

答案 1 :(得分:0)

是的。您可以在基于类的视图中使用get_object_or_404。只需将其添加到您的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)

有关更多信息,您可以在django官方网站上阅读dynamic filtering in class-based views