用基于类的通用视图处理表单(Class-based generic views)

from:http://www.cnblogs.com/huafeng/p/3273421.html

处理表单通常包含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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值