django 1.8 官方文檔翻譯: 3-4-3 使用基於類的視圖處理表單

使用基於類的視圖處理表單

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

  • form_valid()的默認實現只是簡單地重定向到success_urlorm

模型的表單

通用視圖在於模型一塊兒工做時會真正光芒四射。這些通用的視圖將自動建立一個ModelForm,只要它們能知道使用哪個模型類:

  • 若是給出model屬性,則使用該模型類。

  • 若是get_object() 返回一個對象,則使用該對象的類。

  • 若是給出queryset,則使用該查詢集的模型。

模型表單提供一個form_valid() 的實現,它自動保存模型。若是你有特殊的需求,能夠覆蓋它;參見下面的例子。

你甚至不須要爲CreateViewUpdateView提供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 異常。

若是你同時指定fieldsform_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

在這個例子中:

  • CreateViewUpdateView 使用 myapp/author_form.html

  • DeleteView 使用 myapp/author_confirm_delete.html

若是你但願分開CreateViewUpdateView 的模板,你能夠設置你的視圖類的template_nametemplate_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 文檔協做翻譯小組,原文:Built-in editing views

本文以 CC BY-NC-SA 3.0 協議發佈,轉載請保留做者署名和文章出處。

Django 文檔協做翻譯小組人手緊缺,有興趣的朋友能夠加入咱們,徹底公益性質。交流羣:467338606。

相關文章
相關標籤/搜索