Django的class-based-view是基于function-based-view而言的, 其产生的原因是因为在网站开发的过程中,其实是有很多的共同的模式的. 比如今天要简单介绍的list-detail模式.很多的网页其实都包含这样的模式的, 比如我们拿BAT举例,百度的搜索结果页就是一个list,但是你点击某一个链接时, 你就进入到了的detail;淘宝也是一样,当你搜索”外套”时,出来的也都是list, 然后当你选中你想要细看的宝贝时,你也进入到了detail;QQ聊天就更明显了, 打开软件看到的是”好友列表”,然后想和谁聊天,双击,就进入了detail.

在网站开发中,比如你要开发一个新闻网站,那么,首先你要有一个新闻列表页, 对应list,那么如果用function-based-view应该是这样写:

from django.shortcuts import render
from django.utils.safestring import mark_safe

def index(request):
    news = News.objects.all()
    ret = {
        'news': news,
    }
    return render(request, "news/index.html", ret)

对应的urls.py是这个样子:

from django.conf.urls import url
import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

然后是具体的新闻页面,即detail,代码如下:

def detail(request, news_id):
    news = News.objects.get(id=news_id)
    ret = {
        'title': mark_safe(news.title),
        'content': mark_safe(news.content),
    }
    return render(request, "news/detail.html", ret)

urls.py也就变成了这样:

from django.conf.urls import url
import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^detail/(?P<news_id>\d+)/$', views.detail, name='detail'),
]

代码量不算很大,但是假设现在要添加一个模块,叫新闻人物, 其逻辑基本上和新闻是一样的,也是list-detail模式, 你是不是就要ctrl+c然后ctrl+v然后把所有上面的”News”变成”People”? 这就是重复劳动了,怎么避免呢?万能的Django早已准备好了对付list-detail的类, 对于上面的代码,改造过程如下:

from django.views.generic import ListView
from django.views.generic import DetailView

class NewsList(ListView):
    model = News

class NewsDetail(DetailView):
    model = News

urls.py变成如下:

from django.conf.urls import url
import views

urlpatterns = [
    url(r'^list2/$', views.NewsList.as_view(), name='index'),
    url(r'^detail2/(?P<pk>[0-9]+)/$', views.NewsDetail.as_view(), name='detail'),
]

这是是不是很简单了?整个list-detail的逻辑全部在Django内部解决了, 你只需要告诉Django你的list-detail主题model是谁就可以了.当然, 很多工作不是不需要做了,而是由Django替你做了,比如,templates的指定, Django为list默认去寻找templates/app_name/model_name_list.html, 为detail默认去寻找templates/app_name/model_name_detail.html. 而且这也是可以改变的,你可以通过类的template_name属性来设置, 如下:

from django.views.generic import ListView
from django.views.generic import DetailView

class NewsList(ListView):
    model = News
    template_name = "my_own_templates.html"

class NewsDetail(DetailView):
    model = News
    context_object_name = 'the_news'

上面的context_object_nameview传给templates的变量名, 默认是model_name_listmodel_name,可以通过这个属性自定义.

其实,还可以更简单点:那就是只有urls.py:

from django.conf.urls import url
from django.views.generic import ListView
from django.views.generic import DetailView
import models
import views

urlpatterns = [
    url(r'^list3/$', ListView.as_view(model=models.News), name='index'),
    url(r'^detail3/(?P<pk>[0-9]+)/$', DetailView.as_view(model=models.News), name='detail'),
]

这样连views.py都不需要了,当你需要新的新闻人物时,你需要做的就是添加如下两行就可以了:

    url(r'^list4/$', ListView.as_view(model=models.People), name='p-index'),
    url(r'^detail4/(?P<pk>[0-9]+)/$', DetailView.as_view(model=models.People), name='p-detail'),

是不是很简洁呢?



blog comments powered by Disqus

Published

18 November 2015

Category

tech_world

Tags