一个视图(view)是一个可调用对象(callable), 不仅仅局限于一个函数。
https://docs.djangoproject.com/en/1.8/ref/class-based-views/
== 介绍
基于类的视图(class-based views)相比较于基于函数的视图(function-based views)的不同和优点:
* 处理不同HTTP方法(GET,POST,etc)的代码可以定位到不同的函数,而不是使用不同条件分支。
* 如mixin(多重继承)的面相对象技术,可以用于将代码组织成可以复用的模块。
- 使用基于类的视图(view)
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')
在基于类的方法中,你没有必要使返回与基于函数的方法保持一致,即返回某种形式的HttpResponse.
意味着http shortcuts和TemplateResponse对象在基于类的方法中可用。
有两种方法设置类的属性:
class MorningGreetingView(GreetingView):
greeting = "Morning to ya"
或
urlpatterns = [
url(r'^about/', GreetingView.as_view(greeting="G'day")),
]
- 使用Mixins
Mixins是一种形式的多重继承,多个父类的行为和方法可以被组合。
- 处理forms
from .forms import MyForm
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
return render(request, self.template_name, {'form': form})
- 修饰符
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = [
url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
class ProtectedView(TemplateView):
template_name = 'secret.html'
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)
== 内建的基于类的通用显示视图(generic views)
* 为单个对象显示列表和详情页面
* 为基于日期的对象按year/month/day显示归档页面,及详情、最近页面。
* 允许用户create,update,delete对象 - 在认证或未认证情况下。
- 扩展通用视图
推荐通过继承子类和override属性及方法来扩展generic views,而不是在URLCong中传入大量配置。
- 通用视图对象
# models.py
from django.db import models
class Publisher(models.Model):
只需添加下列代码:
# views.py
class PublisherList(ListView):
model = Publisher # queryset = Publisher.objects.all()
# urls.py
urlpatterns = [
url(r'^publishers/$', PublisherList.as_view()),
]
当然,还需要写一个模板(template).
我们可以显示的通过添加template_name属性指明template路径,
如果不显示指定,Django根据对象名使用默认路径"books/publisher_list.html"
# 渲染时context包含一个object_list变量包含所有对象,及publisher_list
{% extends "base.html" %}
{% block content %}
<h2>Publishers</h2>
<ul>
{% for publisher in object_list %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
{% endblock %}
# context_object_name
class PublisherList(ListView):
model = Publisher
context_object_name = 'my_favorite_publishers'
- 在context中添加其他信息
class PublisherDetail(DetailView):
model = Publisher
def get_context_data(self, **kwargs):
# 获取context
context = super(PublisherDetail, self).get_context_data(**kwargs)
# 添加QuerySet of all the books
context['book_list'] = Book.objects.all()
return context
- 只显示列表子集
class PublisherDetail(DetailView):
context_object_name = 'publisher'
queryset = Publisher.objects.all()[:10]
class BookList(ListView):
queryset = Book.objects.order_by('-publication_date')
context_object_name = 'book_list'
- 动态过滤
urlpatterns = [
url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),
]
class PublisherBookList(ListView):
template_name = 'books/books_by_publisher.html'
def get_queryset(self):
self.publisher = get_object_or_404(Publisher, name=self.args[0])
return Book.objects.filter(publisher=self.publisher)
def get_context_data(self, **kwargs):
context = super(PublisherBookList, self).get_context_data(**kwargs)
context['publisher'] = self.publisher
return context
- 其他用法
class AuthorDetailView(DetailView):
queryset = Author.objects.all()
def get_object(self): # 获取对象时调用
object = super(AuthorDetailView, self).get_object()
object.last_accessed = timezone.now() # 更新访问时间
object.save()
return object
== 内建的基于类的通用编辑视图 (Forms)
== 在基于类的视图中使用Mixins