1,什么时候用类,什么时候用函数?
只要代码逻辑被重复使用,同时有需要共享的数据,则可以封装出一个类,这样可以享用类提供的好处----继承和复用。如果这种情况下依旧使用函数的话,就要定义多个子函数,通过函数级别的复用达到目的,但问题在于不够结构化,无法通过继承类,然后修改配置,或者重写某个方法达到目的
2,理解class-based view
django提供了以下几个class-based view
<1>View 基础的view,它基于Http方法的分发逻辑,比如get请求会调用相应的get方法,post请求会调用post方法,但自己没有实现具体的get或者post方法
<2>TemplateView,继承自View,可以直接用来返回指定的模板。它实现了get方法,直接传递变量到模板中实现数据展示
<3>List View,实现了get方法,可通过绑定模板批量获取数据
<4>Detail View,实现了get方法,可以绑定某一模板,来获取单个实例的数据
示例:
#1,function view
def my_view(request):
if request.method == 'GET':
......
#2,class-based view
class my_view(View):
def get(self,request):
....
好处:解耦了Http GET请求及其他请求,如果要增加处理post请求的逻辑,只需要增加函数def post即可
3,Detail View
<1>示例
from django.views import generic
class DetailView(generic.DetailView):
model = Article
template_name = 'blog/detail.html'
context_object_name = 'article'
我们只是继承了DetailView,配置了model与template_name,就能渲染数据,因为对于单个数据的请求,Django帮我们封装好了数据获取的逻辑,我们秩序配置即可
<2>常用属性及接口
属性:
model:指定当前View要用的Model
queryset:与model一样,设定基础的数据集,但model设定无过滤功能
templage:模板名称
context_object_name:获取要用于对象的名称
接口:
get_queryset:用来获取数据
get_object:根据url参数,从queryset上获取对应实例
get_context_data:获取渲染到模板中的所有上下文
<3>url定义
from .views import DetailView
url(r'^article/(?P<pk>\d+)/$',DetailView.as_view(),name='detail'),#文章详情
通过as_view()函数来接受请求并返回响应(下面会讲到as_view())
指定了要匹配的参数pk作为过滤post数据的参数,从而产生了这样的请求:
Post.objects.filter(ok=pk),以拿到文章的实例
4,ListView
<1>示例
class IndexView(generic.ListView):
model=Article
template_name='blog/index.html'
context_object_name='articles'
paginate_by=5
<2>常用属性及接口
paginate_by指定了每页显示多少条数据
get_ordering接口:返回用于queryset排序的一个或多个字段
def get_ordering(self):
ordering = super(IndexView, self).get_ordering()
#self.kwargs的数据是我们从url定义中拿到的
sort = self.kwargs.get('sort')
if sort == 'v':
return ('-views', '-update_date', '-id')
return ordering
#url定义
url(r'^category/(?P<slug>[\w-]+)/hot/$', CategoryView.as_view(), {'sort': 'v'},
name='category_hot'),
get_queryset接口用来获取数据
#解决主页文章列表显示n+1问题
def get_queryset(self,**kwargs):
queryset=super(IndexView,self).get_queryset()
return queryset.select_related('author','category')
5,django中的view如何处理请求
django接受一个请求后(严格说是http请求,不过http请求会被django转化为request对象),请求会先经过所有middleware的process_request方法,然后解析url,接着根据配置的url和view的映射,把request对象传递到view中,view有两种:
<1>funciton view处理的逻辑比较好理解,就是简单的函数,流程就是函数的执行流程,只是第一个参数是request对象
<2>class-based view对外暴露的接口是as_view(),as_view()其实只做了一件事,那就是返回一个闭包,这个闭包会在django解析完之后调用,这个闭包会给class(我们定义的view)赋值,如reqeuts,args,kwargs,然后根据http方法分发请求,如get请求会调用class.get方法,post请求会调用class.post方法
请求到达后(如get请求)
用dispatch分发,接着调用get方法
在get请求中,先调用get_queryset方法,拿到数据源
然后调用get_context_data,拿到要渲染到模板中的数据(此时可以传一些额外的内容到网页),在get_context_data中,先调用get_paginate_by拿到每页数据,然后调用get_context_object_name拿到queryset名称,然后调用paginate_queryset进行分页处理,最后拿到的数据转化为dict并返回
调用render_to_response渲染数据到页面,在render_to_response中调用get_template_names拿到模板名,然后把request,context,template_name等传递到模板中