django 1.8 官方文档翻译: 3-4-3 使用基于类的视图处理表单

神经接口师
• 阅读 1798

使用基于类的视图处理表单

表单的处理通常有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() 的实现,它自动保存模型。如果你有特殊的需求,可以覆盖它;参见下面的例子。

你甚至不需要为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。

点赞
收藏
评论区
推荐文章
Karen110 Karen110
4年前
盘点JavaScript 事件和方法提交那些事儿
大家好,我进阶学习者。一、前言提交表单时,会触发submit事件,它通常用于在将表单发送到服务器之前对表单进行校验,或者中止提交,并使用JavaScript来处理表单。form.submit()方法允许从JavaScript启动表单发送。可以使用此方法动态地创建表单,并将其发送到服务器。二、事件:submit1\.提交表单主要有两种方式
Wesley13 Wesley13
3年前
jabdp自定义表单
第6章 自定义表单1、描述自定义表单是一个虚拟表,其内容由SQL语句查询定义,类似于数据库中的视图,但是功能更丰富。自定义表单的内容来源于一张或多张实体表,通过select语句来查询定义。关联的实体表的数据发生变化的时候,自定义表单查询出来的内容也会同步发生变化。2、作用自定义表单的的好处主要有以下两点:把
【ReportDesign】100行代码搞定一个功能完整的报表页,你不心动吗?
使用文档地址:http://43.143.54.159/github地址:https://github.com/hunanliy/reportdesignReportDesign是一款基于ElementUI进行扩展的Vue开源组件库,以数据驱动视图,通过简单的配置生成一个完整的页面,主要包含Form表单、Table表格、Report报表和DialogS
Stella981 Stella981
3年前
Play 2.0 用户指南 - 文件上传 -- 针对Scala开发者
   处理文件上传   在form中指定multipart/formdata属性上传文件   上传文件的标准方式是指定form的一个特殊属性multipart/formdata,可以让你混合表单数据和表单文件附件。   开始编写HTML表单:@form(actionrou
Stella981 Stella981
3年前
Spring Boot 2 + Thymeleaf:表单字段绑定、表单提交处理
SpringBoot中Thymeleaf对表单处理的一些用法:(1)使用th:field属性:进行表单字段绑定(2)使用ids对象:一般用于lable配合radio或checkbox使用(3)表单提交处理开发环境:IntelliJIDEA2019.2.2SpringBoot版本:2.1.8新建一个名称为demo的Spr
Stella981 Stella981
3年前
ASP.NET WebApi服务接口如何防止重复请求实现HTTP幂等性
一、背景描述与课程介绍明人不说暗话,跟着阿笨一起玩WebApi。在我们平时开发项目中可能会出现下面这些情况;1)、由于用户误操作,多次点击网页表单提交按钮。由于网速等原因造成页面卡顿,用户重复刷新提交页面。黑客或恶意用户使用postman等工具重复恶意提交表单(攻击网站)。这些情况都会导致表单重复提交,造成数据重复
Stella981 Stella981
3年前
Django学习笔记之Django Form表单详解
_知识预览_构建一个表单在Django中构建一个表单DjangoForm类详解使用表单模板回到顶部构建一个表单假设你想在你的网站上创建一个简单的表单,以获得用户的名字。你需要类似这样的模板:<formaction"/yourname/"method"post"
Stella981 Stella981
3年前
Play 2.0 用户指南 - 表单提交和验证 --针对Scala开发者
处理表单提交   定义一个表单   play.api.data包中包含了一些助手方法,用于处理HTTP表单数据提交和验证。操纵表单提交最容易的方式是定义一个play.api.data.Form结构:importplay.api.data._importplay.api.data.F
Stella981 Stella981
3年前
Django 表单处理流程
Django的表单处理:视图获取请求,执行所需的任何操作,包括从模型中读取数据,然后生成并返回HTML页面(从模板中),我们传递一个包含要显示的数据的上下文。使事情变得更复杂的是,服务器还需要能够处理用户提供的数据,并在出现任何错误时,重新显示页面。下面显示了Django如何处理表单请求的流程图,从对包含表单的页面的请求开始(以绿色显示):!(
实现动态表单的一种思路 | 京东云技术团队
一、动态表单是什么区别于传统表单前后端配合联调的开发实现方式,动态表单通过一种基于元数据管理的配置化方法来实现表单的动态生成,并能根据配置自由增改删指定字段。实现特定需求的自助化。图1.1传统表单前后台协作模式图1.2动态表单前后台协作模式二、解决什么问题
鸿蒙小林 鸿蒙小林
2个月前
《伴时匣》app开发技术分享--表单提交页(5)
技术栈Appgalleryconnect开发准备上一节我们已经实现了表单信息的创建,完成了首页跳转表单提交页的内容,这一节我们就要实现表单创建前的数据填充的页面。功能分析在表单提交前,我们要实现的静态内容有很多,分别有输入框,开关,时间选择器,表类型,是否