表單的處理一般有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。