Class-based views
官方推荐使用通用视图类
- 简单示例
# models.py from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: ordering = ["-name"] def __str__(self): # __unicode__ on Python 2 return self.name
# views.py from django.views.generic import ListView from books.models import Publisher class PublisherList(ListView): # model类属性指定了使用的数据模型 model = Publisher # 如不指定template_name属性,Django会自动为该类指定一个模板路径(比方该类的默认路径为"books/publisher_list.html",books是app名称) # 同时会自动将查找的结果指向'object_list'变量,从而可以在模板中直接使用
# urls.py from django.conf.urls import url from books.views import PublisherList urlpatterns = [ # PublisherList并不是视图函数,因此不能直接调用,而需要调用as_view()类方法 url(r'^publishers/$', PublisherList.as_view()), ]
- 指定模板使用的环境变量名
class PublisherList(ListView): model = Publisher # 通过context_object_name类属性来指定 context_object_name = 'my_favorite_publishers'
- 添加额外的环境变量
重载get_context_data()
方法from django.views.generic import DetailView from books.models import Publisher, Book class PublisherDetail(DetailView): model = Publisher def get_context_data(self, **kwargs): # Call the base implementation first to get a context context = super(PublisherDetail, self).get_context_data(**kwargs) # Add in a QuerySet of all the books context['book_list'] = Book.objects.all() # 最终返回context return context
-
指定视图类使用的对象
除了使用model
属性外,通过queryset
属性也可以指定视图类处理的对象from django.views.generic import ListView from books.models import Book class BookList(ListView): # 该视图类处理的对象由queryset指定,这样做的好处是可以更明确地处理返回结果 queryset = Book.objects.order_by('-publication_date') context_object_name = 'book_list'
-
自动筛选对象
如果通过model
或者queryset
来指定查找对象,面对不同的筛选条件,需要定义不同的视图类,这样做就会显得很繁琐
Django提供了get_queryset()
方法来处理不同的筛选条件当调用视图类时,绝大多数的信息将保存在self中(如
self.request
);其中self.args将保存URLconf传入的位置参数,self.kwargs
将保存URLconf传入的关键字参数# urls.py urlpatterns = [ # 正则表达式中有一个位置参数,将保存到其调用的视图类(PublisherBookList)的self.args中 url(r'^books/([\w-]+)/$', PublisherBookList.as_view()), ]
# views.py from django.shortcuts import get_object_or_404 from django.views.generic import ListView from books.models import Book, Publisher class PublisherBookList(ListView): template_name = 'books/books_by_publisher.html' # 该方法返回视图类的处理对象 def get_queryset(self): # 此处用self的publisher属性指向所得结果是为了在后续方法中也可以使用该对象 # self.args保存的是位置参数列表 self.publisher = get_object_or_404(Publisher, name=self.args[0]) return Book.objects.filter(publisher=self.publisher) # 该方法添加环境变量 def get_context_data(self, **kwargs): # Call the base implementation first to get a context context = super(PublisherBookList, self).get_context_data(**kwargs) # Add in the publisher # 此处就使用到了上文中定义的self.publisher对象 context['publisher'] = self.publisher return context
- 对象预处理/善后
get_object()
方法可以获得将要处理的对象,通过对该方法的重载,可以对对象进行一些额外的处理# urls.py urlpatterns = [ # 对于DetailView的视图类,需要通过pk关键字参数(django默认为pk,也可以指定为其它)来指定所需的对象 url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetailView.as_view(), name='author-detail'), ]
# views.py from django.views.generic import DetailView from django.utils import timezone from books.models import Author class AuthorDetailView(DetailView): # 指定处理对象(实质上是model=Author的另一种表现) queryset = Author.objects.all() # 该方法可用于对对象属性的一些处理 def get_object(self): # Call the superclass object = super(AuthorDetailView, self).get_object() # Record the last accessed date object.last_accessed = timezone.now() object.save() # 最终需要返回对象本身 return object
-
通用编辑视图
主要用于表单视图- FormView
- CreateView
- UpdateView
- DeleteView
主要通过视图类来处理表单
- 基础表单
对于上述表单可以通过FormView来创建视图# forms.py from django import forms class ContactForm(forms.Form): name = forms.CharField() message = forms.CharField(widget=forms.Textarea) def send_eamil(self): # send email using the self.cleaned_data dictionary pass
对于实现了# views.py from myapp.forms import ContactForm from django.views.generic.edit import FormView class ContactView(FormView): template_name = 'contact.html' # form_class指定自定义的表单 # 也可以通过指定model、queryset属性或者重载get_object()方法来使用Django自动生成的表单 form_class = ContactForm # 若表单提交成功,将会转向success_url页面 success_url = '/thanks/' # 该方法用于自动提交合理表单(可以重载) def form_valid(self, form): # This method is called when valid form data has been POSTed. # It should return an HttpResponse. form.send_email() return super(ContactView, self).form_valid(form)
get_absolute_url()
方法的数据模型,CreateView
或者UpdateView
视图函数都无需指定success_url
属性# models.py from django.urls import reverse from django.db import models class Author(models.Model): name = models.CharField(max_length=200) def get_absolute_url(self): return reverse('author-detail', kwargs={'pk': self.pk})
# views.py from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.urls import reverse_lazy from myapp.models import Author # AuthorCreate和AuthorUpdate表单在成功提交会,会自动转向get_absolute_url()方法返回的页面 class AuthorCreate(CreateView): model = Author # fields的用法和ModelForm的Meta类中定义的fields属性一致; # 若ModelForm中没有定义fields属性(即自动生成ModelForm时),则需要在Generic editing views中显示指定 # 因此,若在同一个视图类中同时指定fields和form_class属性,会引发ImproperlyConfigured异常 fields = ['name'] # 可以通过指定template_name属性来设置使用的模板 # 此处并未指定,因此AuthorCreate和AuthorUpdate类默认使用myapp/author_form.html # AuthorDelete类会默认使用myapp/author_confirm_delete.html class AuthorUpdate(UpdateView): model = Author fields = ['name'] class AuthorDelete(DeleteView): model = Author success_url = reverse_lazy('author-list')
# urls.py urlpatterns = [ # URLconf的设置同DetailView一致,需要传入pk关键字参数指定使用的具体数据 url(r'author/add/$', AuthorCreate.as_view(), name='author-add'), url(r'author/(?P<pk>[0-9]+)/$', AuthorUpdate.as_view(), name='author-update'), url(r'author/(?P<pk>[0-9]+)/delete/$', AuthorDelete.as_view(), name='author-delete'), ]
-
通用日期视图
主要用于展示归档信息- ArchiveindexView
- YearArchiveView
- MonthArchiveView
- WeekArchiveView
- DayArchiveView
- TodayArchiveView
- DateDetailView
- Class-based views mixins
- Class-based generic views