Skip to content

Latest commit

 

History

History
168 lines (125 loc) · 4.98 KB

十二、ClassBasedView.md

File metadata and controls

168 lines (125 loc) · 4.98 KB
title date tags
ClassBasedView
2018-04-06 06:08:08 -0700
DJango

十二、ClassBasedView

Class BasedView可以让我们的代码变的可扩展,减少视图函数的重复代码提升开发效率

  • View: 用来处理简单的视图
  • TemplateView: 继承自view,渲染模板
  • ListView: 展示一个Model数据的view,比如文章列表
  • DetailView: 展示一个Model内的多条数据

首先,我们需要更改url, as_view()意思是将类视图转换为函数视图,IndexView就是列表视图 PostView就是正文视图

# urls.py
from blog.views import IndexView, CategoryView, TagView, PostView

urlpatterns = [
    url(r'^$', IndexView.as_view(), name="index"),
    url(r'^category/(?P<category_id>\d+)/$', CategoryView.as_view(), name="category"),
    url(r'^tag/(?P<tag_id>\d+)/$', TagView.as_view(), name="tag"),
    url(r'^post/(?P<pk>\d+)/$', PostView.as_view(), name="detail"),

接下里重写views.py,IndexView,CategoryView,TagView都是指向文章post的,所以这里写一个父类BasePostView

  • model = Post 告诉Django我们要获取的模型是post
  • template_name:指定模板
  • context_object_name:指定获取的模型列表数据保存的变量名,这个变量会被传递给模板,和函数试图中的context一样
from django.views.generic import ListView, DetailView


class BasePostView(ListView):
    """
    IndexView,CategoryView,TagView都是指向文章post的,所以这里写一个父类BasePostView
    """
    model = Post
    template_name = "blog/list.html"
    context_object_name = "posts"


class IndexView(BasePostView):
    pass


class CategoryView(BasePostView):
	"""覆写get_queryset方法
	    1、该方法默认获取指定模型的全部列表数据,为了获取指定分类下的文章列表数据,我们覆写该方法,改变它的默认行为
	    2、self.kwargs从url中得到category_id
	    3、get_queryset获取全部文章后再使用filter来过滤分类并返回
    """
    def get_queryset(self):
        qs = super(CategoryView, self).get_queryset()
        # self.kwargs:获取url中的名字,(?P<category_id>\d+)
        cate_id = self.kwargs.get("category_id")
        qs = qs.filter(category_id=cate_id)
        return qs


class TagView(BasePostView):
    def get_queryset(self):
        tag_id = self.kwargs.get("tag_id")
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            return []
        posts = tag.posts.all()
        return posts


class PostView(DetailView):
    model = Post
    template_name = "blog/detail.html"
    context_object_name = "post"

设置分页 CBV也内置了分页功能,非常简单

https://docs.djangoproject.com/en/2.0/topics/class-based-views/mixins/

在父类BasePostView中添加如下代码,表示一页有三篇文章

paginate_by = 3

再重写list.html

 {% if page_obj.has_previous %}<a href="?page={{ page_obj.previous_page_number }}">上一页</a>
        {% endif %}
        Page {{ page_obj.number }} of {{ paginator.num_pages }}.
        {% if page_obj.has_next %}<a href="?page={{ page_obj.next_page_number }}">下一页</a>
        {% endif %}

好了,分页就结束了

通用代码 博客的列表页和正文页都是需要侧边栏和分类导航的,这里我们使用到了多重继承Mixin,把Mixin写入BasePostView和PostView,这里我们把分类挑了出来也可以把sidebar挑出来

class CommonMixin(object):
    def get_category_context(self):
        """分类
            1、nav_cates = categoryies.filter(is_nav=True) 导航分类
            2、cates = categories.filter(is_nav=False) 普通分类
            3、Category.objects.all()返回一个queryset对象复制给categories
        """
        categories = Category.objects.all()
        cates = []
        nav_cates = []
        for category in categories:
            if category.is_nav:
                nav_cates.append(category)
            else:
                cates.append(category)
        return {
            "nav_cates": nav_cates,
            "cates": cates,
        }

    def get_context_data(self, **kwargs):
        """
        侧边栏
        """
        sidebars = SideBar.objects.filter(status=1)
        recently_posts = Post.objects.filter(status=1)[:5]
        recently_comments = Comment.objects.filter(status=1)[:2]
        kwargs.update({
            "sidebars": sidebars,
            "recently_posts": recently_posts,
            "recently_comments": recently_comments,
        })
        kwargs.update(self.get_category_context())
        return super(CommonMixin, self).get_context_data(**kwargs)
class BasePostView(CommonMixin, ListView):

..........


class PostView(CommonMixin, DetailView):

GitHub 欢迎访问Treehl的博客