处理表单通常包含3步:

  • 初始化GET(空白的后者预填充的表单)

  • POST非法数据(通常重新显示带有错误信息的表单)

  • POST合法数据(提交数据并重定向)

为了将你从这些烦人的重复步骤中解救出来,Django为表单提供了一类通用视图

基础表单

这是一个简单的联系表单:

1
2
3
4
5
6
7
8
9
10
# 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来构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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()(如果存在的话)。你也可以简单地设置form_class来定制一个ModelForm(为模型添加额外的验证)

注意当指定一个定制的表单类时,你也必须指定模型,尽管form_class可能就是一个ModelForm

首先我们需要添加为Author类添加get_absolute_url()

1
2
3
4
5
6
7
8
9
# 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和它的朋友们来做实际的工作。注意我们在这里如何匹配基于类的通用视图,我们不必写任何的逻辑代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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
 
class AuthorUpdate(UpdateView):
    model = Author
 
class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

注意:这里必须要用reverse_lazy(),而不仅仅是reverse,因为当文件被导入时urls没有被加载

最后,我们在URLconf中加上这些新的视图:

1
2
3
4
5
6
7
8
9
10
# urls.py
from django.conf.urls import patterns, url
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete
 
urlpatterns = patterns('',
    # ...
    url(r'author/add/$', AuthorCreate.as_view(), name='author_add'),
    url(r'author/(?P<pk>\d+)/$', AuthorUpdate.as_view(), name='author_update'),
    url(r'author/(?P<pk>\d+)/delete/$', AuthorDelete.as_view(), name='author_delete'),
)

注意:这些视图都继承于SingleObjectTemplateMinxin,这个类使用template_name_suffix来构造基于模型的template_name

在这个例子中:

  • CreateView和UpdateView使用myapp/author_form.html

  • DeleteView使用myapp/author_confirm_date.html

如果你想要为CreateView和UpdateView使用不同的模板,你可以在你的视图类里设置template_name或者template_name_suffix

模型和request.user

为了跟踪用户使用CreateView创建对象,你可以使用定制的ModelForm来实现它。

首先,为模型增加外键:

1
2
3
4
5
6
7
8
9
# models.py
from django.contrib.auth import User
from django.db import models
 
class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User)
 
    # ...

创建一个定制的ModelForm来隔离created_by,以免用户去编辑它:

1
2
3
4
5
6
7
8
# forms.py
from django import forms
from myapp.models import Author
 
class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        exclude = ('created_by',)

在这个视图中,使用定制的form_class并重写form_valid()来增加user:

1
2
3
4
5
6
7
8
9
10
11
12
# views.py
from django.views.generic.edit import CreateView
from myapp.models import Author
from myapp.forms import AuthorForm
 
class AuthorCreate(CreateView):
    form_class = AuthorForm
    model = Author
 
    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super(AuthorCreate, self).form_valid(form)

注意你需要使用login_required()来装饰这个视图,或者在form_valid()里处理未登录的用户

AJAX例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import json
 
from django.http import HttpResponse
from django.views.generic.edit import CreateView
 
class AjaxableResponseMixin(object):
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def render_to_json_response(self, context, **response_kwargs):
        data = json.dumps(context)
        response_kwargs['content_type'= 'application/json'
        return HttpResponse(data, **response_kwargs)
 
    def form_invalid(self, form):
        response = super(AjaxableResponseMixin, self).form_invalid(form)
        if self.request.is_ajax():
            return self.render_to_json_response(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 self.render_to_json_response(data)
        else:
            return response
 
class AuthorCreate(AjaxableResponseMixin, CreateView):
    model = Author

转载请注明出处

用基于类的通用视图处理表单(Class-based generic views)的更多相关文章

  1. Django 基于类的通用视图

    在早期,我们认识到在视图开发过程中有共同的用法和模式.这时我们引入基于函数的通用视图来抽象这些模式以简化常见情形的视图开发. 基于函数视图的用法有以下三种: def index(request): r ...

  2. Django 1.6 基于类的通用视图

    Django 1.6 基于类的通用视图 最初 django 的视图都是用函数实现的,后来开发出一些通用视图函数,以取代某些常见的重复性代码.通用视图就像是一些封装好的处理器,使用它们的时候只须要给出特 ...

  3. Django——django1.6 基于类的通用视图

    最初 django 的视图都是用函数实现的,后来开发出一些通用视图函数,以取代某些常见的重复性代码.通用视图就像是一些封装好的处理器,使用它们的时候只须要给出特定的参数集即可,不必关心具体的实现.各种 ...

  4. 基于类的通用视图(Class-based generic views)

    在web开发中,最令人头痛的就是一遍又一遍的重复固定的模式.在解决了模板层面和模型层面的重复代码之痛之后,Django使用通用视图来解决视图层面的代码重复. 扩展通用视图 毫无疑问通用视图可以大幅度地 ...

  5. 基于jQuery会员中心安全修改表单代码

    基于jQuery会员中心安全修改表单代码.这是一款登录密码,交易密码,手机号码,实名认证,电子邮箱,安全设置表单,会员表单等设置代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: ...

  6. 一款基于jquery ui的动画提交表单

    今天要给大家分享一款基于jquery ui的动画提交表单.这款提交表单的的效果是以动画的形式依次列表所需填写的信息.效果非常不错,效果图如下: 在线预览   源码下载 实现的代码. html代码: & ...

  7. YII用户注冊和用户登录(二)之登录和注冊在视图通过表单使用YII小物件并分析

    2 登录和注冊在视图通过表单使用YII小物件并分析 <?php $form = $this -> beginWidget('CActiveForm', array( 'enableClie ...

  8. Laravel 5 基础(十一)- 子视图和表单复用

    我们需要处理编辑文章的问题.当然我们可以手工添加新的路由,就像这样: Route::get('/articles/{id}/edit', 'ArticleController@edit'); 让我们在 ...

  9. 【表单验证】基于jQuery的高度灵活的表单验证(无UI)

    表单验证是前端开发过程中常见的一个需求,产品需求.业务逻辑的不同,表单验证的方式方法也有所区别.而最重要的是我们要清楚,表单验证的核心原则是--错误信息提示准确,并且尽可能少的打扰/干扰用户的输入和体 ...

随机推荐

  1. Struts2之基于配置的字段校验

    上一篇struts2之输入校验介绍了手动完成输入校验,也即依靠重写validate方法和validateXxx方法,指定请求某个方法时对传入的参数进行校验. 本篇介绍基于配置的字段校验.下面是登录的常 ...

  2. nodejs的http-server--web前端福利

    很多web前端在日常开发的时候可能会想常开发是谁. 不好意思,说错了. 很多web前端在日常开发的时候总是避免不了让所写页面在服务器环境下执行. 比如当你在用angularjs的route模块等等等. ...

  3. oauth2.0协议接口-第一篇-api逻辑

    开放平台是支持OAuth2.0和RESTful协议的资源分享平台,经过授权的合作伙伴可以读取和写入资讯.用户.文件.数据库等资源. 1.创建数据库表结构 CMSSyncClient(数据同步客户端) ...

  4. python3.X中pickle类的用法(cPickle模块移除了)

    1.python3.x中移除了cPickle模块,可以使用pickle模块代替.最终我们将会有一个透明高效的模块. 2.因为存储的是对象,必须使用二进制形式写进文件 #!/usr/bin/python ...

  5. 10 ajax

    Ajax准备知识:json 什么是json? 定义: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式.它基于 ECMAScript (w ...

  6. Java-多线程与单例

    最近在公司写需求时遇到了多线程与单例一同出现的情况. 这个时候想到的就是线程安全以及单例的定义了,虽然单例指的是在内存中它只有一份,但是并不是说就是线程安全的. 所以,我当时就到网上找了关于多线程下单 ...

  7. easyui 获取树的平级根节点的父节点&选择性展示树的一个根节点

    1.easyui的树的根节点一般是几个平级的,怎样获取这些父节点的id? 可以将获取到的平级根节点放在一个数组中 var roots=[]; roots=$("#tree1").t ...

  8. 四大VDI客户端 总有一款适合你

    [TechTarget中国原创] 交付虚拟桌面时IT管理员必须要考虑到用户如何访问虚拟桌面,因为这会影响用户体验以及VDI部署最终的成败. IT可以转向简便的HTML5客户端,HTML 5客户端功能丰 ...

  9. 剑指Offer - 九度1351 - 数组中只出现一次的数字

    剑指Offer - 九度1351 - 数组中只出现一次的数字2013-11-23 01:23 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. ...

  10. USACO Section1.3 Combination Lock 解题报告

    combo解题报告 —— icedream61 博客园(转载请注明出处)---------------------------------------------------------------- ...