表单的处理一般有3 个步骤:html
初始的的GET (空白或预填充的表单)python
带有非法数据的POST(一般从新显示表单和错误信息)ajax
带有合法数据的POST(处理数据并重定向)django
你本身实现这些功能常常致使许多重复的样本代码(参见在视图中使用表单)。为了不这点,Django 提供一系列的通用的基于类的视图用于表单的处理。app
根据一个简单的联系人表单:ui
#forms.py from django import forms class ContactForm(forms.Form): name = forms.CharField() message = forms.CharField(widget=forms.Textarea) def send_email(self): # send email using the self.cleaned_data dictionary pass
能够使用FormView
来构造其视图:url
#views.py from myapp.forms import ContactForm from django.views.generic.edit import FormView class ContactView(FormView): template_name = 'contact.html' form_class = ContactForm 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)
注:翻译
FormView
继承TemplateResponseMixin
因此这里能够使用template_name
。code
form_valid()
的默认实现只是简单地重定向到success_url
。orm
通用视图在于模型一块儿工做时会真正光芒四射。这些通用的视图将自动建立一个ModelForm,只要它们能知道使用哪个模型类:
若是给出model
属性,则使用该模型类。
若是get_object()
返回一个对象,则使用该对象的类。
若是给出queryset
,则使用该查询集的模型。
模型表单提供一个form_valid()
的实现,它自动保存模型。若是你有特殊的需求,能够覆盖它;参见下面的例子。
你甚至不须要为CreateView
和UpdateView
提供success_url
—— 若是存在它们将使用模型对象的get_absolute_url()
。
若是你想使用一个自定义的ModelForm
(例如添加额外的验证),只需简单地在你的视图上设置form_class
。
注
当指定一个自定义的表单类时,你必须指定模型,即便form_class
多是一个ModelForm
。
首先咱们须要添加get_absolute_url()
到咱们的Author
类中:
#models.py from django.core.urlresolvers 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})
而后咱们能够使用CreateView
机器伙伴来作实际的工做。注意这里咱们是如何配置通用的基于类的视图的;咱们本身没有写任何逻辑:
#views.py from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.core.urlresolvers import reverse_lazy from myapp.models import Author class AuthorCreate(CreateView): model = Author fields = ['name'] class AuthorUpdate(UpdateView): model = Author fields = ['name'] class AuthorDelete(DeleteView): model = Author success_url = reverse_lazy('author-list')
注
这里咱们必须使用
reverse_lazy()
而不是reverse
,由于在该文件导入时URL 尚未加载。
fields
属性的工做方式与ModelForm
的内部Meta
类的fields
属性相同。除非你用另一种方式定义表单类,该属性是必须的,若是没有将引起一个ImproperlyConfigured
异常。
若是你同时指定fields
和form_class
属性,将引起一个ImproperlyConfigured
异常。
Changed in Django 1.8: 省略fields 属性在之前是容许的,可是致使表单带有模型的全部字段。
Changed in Django 1.8: 之前,若是fields 和form_class 两个都指定,会默默地忽略 fields。
最后,我咱们来将这些新的视图放到URLconf 中:
#urls.py from django.conf.urls import url from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete urlpatterns = [ # ... 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'), ]
注
这些表单继承
SingleObjectTemplateResponseMixin
,它使用template_name_suffix
并基于模型来构造template_name
。在这个例子中:
CreateView
和UpdateView
使用myapp/author_form.html
DeleteView
使用myapp/author_confirm_delete.html
若是你但愿分开
CreateView
和UpdateView
的模板,你能够设置你的视图类的template_name
或template_name_suffix
。
为了跟踪使用CreateView 建立一个对象的用户,你能够使用一个自定义的ModelForm 来实现这点。首先,向模型添加外键关联:
#models.py from django.contrib.auth.models import User from django.db import models class Author(models.Model): name = models.CharField(max_length=200) created_by = models.ForeignKey(User) # ...
在这个视图中,请确保你没有将created_by
包含进要编辑的字段列表,并覆盖form_valid()
来添加这个用户:
#views.py from django.views.generic.edit import CreateView from myapp.models import Author class AuthorCreate(CreateView): model = Author fields = ['name'] def form_valid(self, form): form.instance.created_by = self.request.user return super(AuthorCreate, self).form_valid(form)
注意,你须要使用login_required()
来装饰这个视图,或者在form_valid()
中处理未认证的用户。
下面是一个简单的实例,展现你能够如何实现一个表单,使它能够同时为AJAX 请求和‘普通的’表单POST 工做:
from django.http import JsonResponse from django.views.generic.edit import CreateView from myapp.models import Author class AjaxableResponseMixin(object): """ Mixin to add AJAX support to a form. Must be used with an object-based FormView (e.g. CreateView) """ def form_invalid(self, form): response = super(AjaxableResponseMixin, self).form_invalid(form) if self.request.is_ajax(): return JsonResponse(form.errors, status=400) else: return response def form_valid(self, form): # We make sure to call the parent's form_valid() method because # it might do some processing (in the case of CreateView, it will # call form.save() for example). response = super(AjaxableResponseMixin, self).form_valid(form) if self.request.is_ajax(): data = { 'pk': self.object.pk, } return JsonResponse(data) else: return response class AuthorCreate(AjaxableResponseMixin, CreateView): model = Author fields = ['name']
译者:Django 文档协做翻译小组,原文:Built-in editing views。
本文以 CC BY-NC-SA 3.0 协议发布,转载请保留做者署名和文章出处。
Django 文档协做翻译小组人手紧缺,有兴趣的朋友能够加入咱们,彻底公益性质。交流群:467338606。