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
|