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

表单的处理通常有3 个步骤:

  • 初始的的GET (空白或预填充的表单)
  • 带有非法数据的POST(通常重新显示表单和错误信息)
  • 带有合法数据的POST(处理数据并重定向)

你自己实现这些功能经常导致许多重复的样本代码(参见在视图中使用表单)。为了避免这点,Django 提供一系列的通用的基于类的视图用于表单的处理。

基本的表单

根据一个简单的联系人表单:

#forms.pyfrom django import formsclass ContactForm(forms.Form):name = forms.CharField()message = forms.CharField(widget=forms.Textarea)def send_email(self):# send email using the self.cleaned_data dictionarypass

可以使用FormView来构造其视图:

#views.pyfrom myapp.forms import ContactForm
from django.views.generic.edit import FormViewclass ContactView(FormView):template_name = 'contact.html'form_class = ContactFormsuccess_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.pyfrom django.core.urlresolvers import reverse
from django.db import modelsclass Author(models.Model):name = models.CharField(max_length=200)def get_absolute_url(self):return reverse('author-detail', kwargs={'pk': self.pk})

然后我们可以使用CreateView 机器伙伴来做实际的工作。注意这里我们是如何配置通用的基于类的视图的;我们自己没有写任何逻辑:

#views.pyfrom django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Authorclass AuthorCreate(CreateView):model = Authorfields = ['name']class AuthorUpdate(UpdateView):model = Authorfields = ['name']class AuthorDelete(DeleteView):model = Authorsuccess_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.pyfrom django.conf.urls import url
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDeleteurlpatterns = [# ...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.pyfrom 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.pyfrom django.views.generic.edit import CreateView
from myapp.models import Authorclass AuthorCreate(CreateView):model = Authorfields = ['name']def form_valid(self, form):form.instance.created_by = self.request.userreturn 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 Authorclass 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 responsedef 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 responseclass AuthorCreate(AjaxableResponseMixin, CreateView):model = Authorfields = ['name']

译者:Django 文档协作翻译小组,原文:Built-in editing views。

本文以 CC BY-NC-SA 3.0 协议发布,转载请保留作者署名和文章出处。

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。

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

  1. django 1.8 官方文档翻译: 3-4-5 内建基于类的视图的API

    内建基于类的视图的API 基于类的视图的API 参考.另请参见基于类的视图 的简介. 基础视图 View TemplateView RedirectView 通用的显示视图 DetailView Li ...

  2. django 1.8 官方文档翻译: 3-4-1 基于类的视图

    基于类的视图 视图是一个可调用对象,它接收一个请求然后返回一个响应.这个可调用对象可以不只是函数,Django 提供一些可以用作视图的类.它们允许你结构化你的视图并且利用继承和混合重用代码.后面我们将 ...

  3. django 1.8 官方文档翻译: 3-4-2 基于类的内建通用视图

    基于类的内建通用视图 编写Web应用可能是单调的,因为你需要不断的重复某一种模式. Django尝试从model和 template层移除一些单调的情况,但是Web开发者依然会在view(视图)层经历 ...

  4. django 1.8 官方文档翻译: 3-4-2 内建显示视图

    Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质. 交流群:467338606 网站:http://python.usyiyi.cn/django/index.html ...

  5. django 1.8 官方文档翻译: 5-1-1 使用表单

    使用表单 关于这页文档 这页文档简单介绍Web 表单的基本概念和它们在Django 中是如何处理的.关于表单API 某方面的细节,请参见表单 API.表单的字段和表单和字段的检验. 除非你计划构建的网 ...

  6. django 1.8 官方文档翻译: 1-2-5 编写你的第一个Django应用,第5部分

    编写你的第一个Django应用,第5部分 本教程上接教程第4部分. 我们已经建立一个网页投票应用,现在我们将为它创建一些自动化测试. 自动化测试简介 什么是自动化测试? 测试是检查你的代码是否正常运行 ...

  7. django 1.8 官方文档翻译: 1-2-3 编写你的第一个Django应用,第3部分

    编写你的第一个 Django 程序 第3部分 本教程上接 教程 第2部分 .我们将继续 开发 Web-poll 应用并且专注在创建公共界面 – "视图 (views )". 哲理 ...

  8. django 1.8 官方文档翻译: 3-1-1 URL调度器

    URL调度器 简洁.优雅的URL 模式在高质量的Web 应用中是一个非常重要的细节.Django 允许你任意设计你的URL,不受框架束缚. 不要求有.php 或.cgi,更不会要求类似0,2097,1 ...

  9. django 1.8 官方文档翻译: 2-5-7 自定义查找

    自定义查找 New in Django 1.7. Django为过滤提供了大量的内建的查找(例如,exact和icontains).这篇文档阐述了如何编写自定义查找,以及如何修改现存查找的功能.关于查 ...

最新文章

  1. OpenStack之虚拟机热迁移
  2. sql语句求上四分位数_SAS和R中,非常规分位数的计算方法
  3. python对象三个特性_Python面向对象三大特征之多
  4. Linux环境下安装Tomcat
  5. 打印Java数组最优雅的方式
  6. 算法之旅 | 快速排序法
  7. surfaceView和View区别
  8. python引用、浅拷贝、深拷贝
  9. 打造更安全的视频加密,云点播版权保护实践
  10. H-蛇皮走位(吉首大学2019程序设计校赛)c++
  11. 自我评价中专计算机600作文,中专生毕业的自我评价(精选5篇)
  12. 使用Kali对网站进行DDos攻击
  13. 使用hibernate的@SQLDelete和@Where注解实现逻辑删除
  14. JAVA+selenium+testNG QQ邮箱登录及邮箱发送
  15. 程序人生丨25岁毕业,月薪1万
  16. 李沐-斯坦福《实用机器学习》-02章
  17. 微信小程序----wx.openLocation(OBJECT) 使用微信内置地图查看位置
  18. 详细解读 PolarDB HTAP 的功能特性和关键技术
  19. 获取wifi和基站定位的基础信息
  20. Tomcat执行shutdown时报错:java.net.ConnectException: Connection refused (Connection refused)解决办法

热门文章

  1. Xilinx PLL IP核功能仿真
  2. python嵌套循环优化_减少循环嵌套,提升代码运行速度!你不知道的3个实用Python函数...
  3. 14013.petalinux操作GPIO
  4. 【openMV】算法矫正镜头+视频格式对应的分辨率
  5. ROS 基础: 在同一个节点里订阅和发布消息
  6. 【LeetCode】【HOT】240. 搜索二维矩阵 II(抽象二叉搜索树)
  7. 【LeetCode】剑指 Offer 65. 不用加减乘除做加法
  8. 如何实现Python调用C代码--python与C之间如何通信(swig)
  9. https证书设置以及设置301跳转
  10. Go基础系列:指定goroutine的执行顺序