views.py 是django MTV 中的主要逻辑层,相当于MVC中的 Controller
以下的实例都基于这样一个路由表:
urlpatterns = [ url(r'^(index)?$', views.index, name='index'), url(r'^posts/$', views.PostsView.as_view(), name='posts'), url(r'^article/(?P[0-9]+)/$', views.ArticleView.as_view(), name='detail'),]
view 方法
虽然views.py
是系统自动创建,但是不难发现它并不是必须的。django 关心的是 urls.py
中 import 的是谁。(urls.py 也是项目文件夹下面 urls.py 中引入的)
from django.shortcuts import render, Http404, HttpResponsedef index(request): # return HttpResponse('Hello world') word = request.GET.get('word', '') context = { 'title': 'Dapianzi Carl', 'word': word if s.strip() else '文档里写的很详细,我只是做一点归纳总结', } return render(request, 'app/index.html', context)
view 方法返回一个 <HttpResponse Object>
,可以传递给后面的中间件进行处理。django 封装了一些快捷方法比如 render, getObjectOr404等。
Models.objects.get()
,动不动就给你来一个 DoesNotExists
惊喜 快捷函数
官方文档是最靠谱的
- render 用得最多,上文有粗略介绍。
- redirect 重载多次,功能看起来挺丰富,笔者实际使用不多。需要配合 Models 的 get_absulute_url 方法
- get_object_or_404
- get_list_or_404
view 类
不同于view方法, view 类在路由映射中要用 SomeView.as_view()。
- View 在一个url里根据http method 来处理不同逻辑。处理数据增改操作经常碰到:
class add(View): def get(self, request): # view add form return render(...) def post(self, request): # create new item return redirect(...)
- TemplateView 一般不需要处理参数的页面可以使用。使用它需要定义
template_name
属性和重写get_context_data
方法python class Contact(TemplateView): template_name = 'app/contact.html' def get_context_data(self, **kwargs): # 初始化模板变量 context = super().get_context_data(**kwargs) context['email'] = 'carl@dapianzi.me' context['interest'] = InterestModel.objects.all() return context
DetailView, ListView 高度封装的 列表view 和 内容view
ListView 需要重写get_query_set()
方法,返回的queryset
会赋值给key为context_object_name
属性的 context DetailView 需要指定主键id在 路由表中的名称,然后实现get_object()
方法 ```python class PostsView(ListView): template_name = 'app/posts.html' # 模板中引用的列表变量名称 context_object_name = 'post_list' def get_query_set(self): # 注意获取url参数的方法,request对象被封装在 self.request 中 param = self.request.GET.get('param', '') return Articles.objects.filter(name__contains=param)class ContentView(DetailView):
# 定义模型 model = Article # 模板 template_name = 'app/post.html' # 模板变量名 context_object_name = "post" # url 路由主键id pk_url_kwarg = 'aid' def get_object(self, **kwargs): obj = super(ArticleView, self).get_object() # 对obj进行额外操作,如记录日志,增加浏览数 obj.views+=1 obj.save() return obj ``## 获取参数 如果实现的方法带有request参数,那么直接用
request.GET/request.POST`获取 实现的方法里没有request参数(比如ListView),通常是类里面的一个属性,这个可能需要查文档看源码。。。
其他类型的httpresponse
检查源码或者查看Django文档可以看到有其他类型的Response对象,其实就是文件头不一样而已。下面试导出csv的一个实例:
def export_csv(self, request, queryset): """导出csv""" response = StreamingHttpResponse('\n'.join([','.join( # list元素转str list(map(lambda x: str(x), x)) ) for x in list( # queryset 转 list queryset.values_list('name', 'max_item', 'expire_time', 'active') # charset 非常重要 )]), charset='gbk', content_type='attachment/csv') # 额外的http-headers response['Content-Disposition'] = 'attachment;filename="test.csv"' return response