# 使用基于類的視圖處理表單 #
表單的處理通常有3 個步驟:
+ 初始的的GET (空白或預填充的表單)
+ 帶有非法數據的POST(通常重新顯示表單和錯誤信息)
+ 帶有合法數據的POST(處理數據并重定向)
你自己實現這些功能經常導致許多重復的樣本代碼(參見在視圖中使用表單)。為了避免這點,Django 提供一系列的通用的基于類的視圖用于表單的處理。
## 基本的表單 ##
根據一個簡單的聯系人表單:
```
#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`來構造其視圖:
```
#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`。
+ `form_valid()`的默認實現只是簡單地重定向到`success_url`。
## 模型的表單 ##
通用視圖在于模型一起工作時會真正光芒四射。這些通用的視圖將自動創建一個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`。
## 模型和request.user ##
為了跟蹤使用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 示例 ##
下面是一個簡單的實例,展示你可以如何實現一個表單,使它可以同時為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 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[Built-in editing views](https://docs.djangoproject.com/en/1.8/topics/class-based-views/generic-editing/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架