Django简单入门教程(五)表单
source link: https://vmaig.com/article/django_simple_study_05.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
参考:《The Django Book》 第7章
1. HttpRequest对象的信息
request.path 除域名以外的请求路径,斜杠开头 “/hello/”
request.get_host() 主机名 “127.0.0.1:8000” or “www.xxxx.com”
request.get_full_path() 请求路径,可能包含查询字符串 “/hello/?print=true”
request.is_secure() 是否通过Https访问 是为True,否为False
request.META 一个字典,包含本次Http请求的Header信息 例如 REMOTE_ADDR 表示客户端ip,
HTTP_USER_AGENT表示用户浏览器user-agent字符串
HTTP_REFERER表示进站前连接网页
request.POST 一个类字典对象保存html中<form>标签提交的内容
request.GET 一个类字典对象保存html中<form>标签提交的内容或者URL中的查询字符串
例子:显示request.META 中的所有信息
在view.py中加入下面代码。并在urls.py加上对应的URLpattern
def
test(request):
values
=
request.META.items()
values.sort()
html
=
[]
for
k,v
in
values:
html.append(
'<tr><td>%s</td><td>%s</td></tr>'
%
(k,v))
return
HttpResponse(
'<table>%s</table>'
%
'\n'
.join(html))
2. 一个简单的表单处理
在templates中创建search_form.html模板:
<
html
>
<
head
>
<
title
>Search</
title
>
</
head
>
<
body
>
{% if error %}
<
p
style
=
"color: red;"
>Please submit a search term.</
p
>
{% endif %}
<
form
action
=
''
method
=
'get'
>
<
input
type
=
'text'
name
=
'q'
>
<
input
type
=
'submit'
value
=
'Search'
>
</
form
>
</
body
>
</
html
>
其中action='' 表示表单将提交给与当前页面相同的URL
再添加search_results.html
<
p
>You searched for: <
strong
>{{ query }}</
strong
></
p
>
{% if books %}
<
p
>Found {{ books|length }} book{{ books|pluralize }}.</
p
>
<
ul
>
{% for book in books %}
<
li
>{{ book.title }}</
li
>
{% endfor %}
</
ul
>
{% else %}
<
p
> No books matched your search criteria. </
p
>
{% endif %}
在view.py中添加:
def
search(request):
error
=
False
if
'q'
in
request.GET:
q
=
request.GET[
'q'
]
if
not
q:
error
=
True
else
:
books
=
Book.objects.
filter
(title__icontains
=
q)
return
render_to_response(
'search_results.html'
,
{
'books'
:books,
'query'
:q})
return
render_to_response(
'search_form.html'
,
{
'error'
:error})
其中Book.objects.filter(title__icontains=q) 是用来获取数据库中标题包含q的书籍。icontains是一个查询关键字。
在urls.py 中添加
(r
'search/$'
,search),
然后在浏览器输入 http://127.0.0.1:8000/search/ 可以看到一个简单的搜索界面。
3. 简单的验证
可以用Javascript在客户端浏览器进行验证,但可能有些人会将Javascript关闭,并且还有一些怀有恶意的用户会尝试提交非法的数据来探测是否有可以攻击的机会。所以除了用Javascript在客户端浏览器进行验证外,还需要在服务器验证一次。上面的代码,只对 输入为空做了验证。下面添加一个验证搜索关键字是否小于20个字符的验证。
修改view.py
def
search(request):
errors
=
[]
if
'q'
in
request.GET:
q
=
request.GET[
'q'
]
if
not
q:
errors.append(
'Enter a search term'
)
elif
len
(q) >
20
:
errors.append(
'Please enter at most 20 characters.'
)
else
:
books
=
Book.objects.
filter
(title__icontains
=
q)
return
render_to_response(
'search_results.html'
,
{
'books'
:books,
'query'
:q})
return
render_to_response(
'search_form.html'
,
{
'errors'
:errors})
修改 search_form.html :
<
html
>
<
head
>
<
title
>Search</
title
>
</
head
>
<
body
>
{% if errors %}
{% for error in errors%}
<
p
style
=
"color: red;"
>{{ error }}</
p
>
{% endfor %}
{% endif %}
<
form
action
=
''
method
=
'get'
>
<
input
type
=
'text'
name
=
'q'
>
<
input
type
=
'submit'
value
=
'Search'
>
</
form
>
</
body
>
</
html
>
4. 编写Contact表单
一个较为复杂的例子:这个表单包括用户提交的反馈信息,一个可以选择填不填的e-mail地址。
view.py 中添加:
def
contact(request):
errors
=
[]
if
request.method
=
=
'POST'
:
if
not
request.POST.get(
'subject'
, ''):
errors.append(
'Enter a subject.'
)
if
not
request.POST.get(
'message'
, ''):
errors.append(
'Enter a message.'
)
if
request.POST.get(
'email'
)
and
'@'
not
in
request.POST[
'email'
]:
errors.append(
'Enter a valid e-mail address.'
)
if
not
errors:
send_mail(
request.POST[
'subject'
],
request.POST[
'message'
],
)
return
HttpResponseRedirect(
'/contact/thanks/'
)
return
render_to_response(
'contact_form.html'
, {
'errors'
: errors,
'subject'
: request.POST.get(
'subject'
, ''),
'message'
: request.POST.get(
'message'
, ''),
'email'
: request.POST.get(
'email'
, ''),
},context_instance
=
RequestContext(request))
用POST不用GET,因为这个表单会有一个服务器端的操作:send_mail。
在templates中添加contact_form.html :
<
html
>
<
head
>
<
title
>Contact us</
title
>
</
head
>
<
body
>
<
h1
>Contact us</
h1
>
{% if errors %}
<
ul
>
{% for error in errors %}
<
li
>{{ error }}</
li
>
{% endfor %}
</
ul
>
{% endif %}
<
form
action
=
"/contact/"
method
=
"post"
>
{% csrf_token %}
<
p
>Subject: <
input
type
=
"text"
name
=
"subject"
value
=
"{{ subject }}"
></
p
>
<
p
>Your e-mail (optional): <
input
type
=
"text"
name
=
"email"
value
=
"{{ email }}"
></
p
>
<
p
>Message: <
textarea
name
=
"message"
rows
=
"10"
cols
=
"50"
>{{ message }}</
textarea
></
p
>
<
input
type
=
"submit"
value
=
"Submit"
>
</
form
>
</
body
>
</
html
>
这个例子看起来杂乱,解决方法看下面用forms。
5. from类
上面的那个例子,看起来杂乱,并且容易出错。
Django带有一个form库,称为django.forms,这个库可以处理HTML表单显示以及验证。
新建 forms.py 加入
from
django
import
forms
class
ContactForm(forms.Form):
subject
=
forms.CharField()
email
=
forms.EmailField(required
=
False
)
message
=
forms.CharField()
很像模块中用的语法。默认是每个字段必填的,如果要是可以不填的要指定required=False,就像上面的email字段一样。
来看看forms类到底是什么:它做的第一个是就是将自己显示成HTML
>>>
from
contact.forms
import
ContactForm
>>> f
=
ContactForm()
>>>
print
f
<tr><th><label
for
=
"id_subject"
>Subject:<
/
label><
/
th><td><
input
id
=
"id_subject"
name
=
"subject"
type
=
"text"
/
><
/
td><
/
tr>
<tr><th><label
for
=
"id_email"
>Email:<
/
label><
/
th><td><
input
id
=
"id_email"
name
=
"email"
type
=
"email"
/
><
/
td><
/
tr>
<tr><th><label
for
=
"id_message"
>Message:<
/
label><
/
th><td><
input
id
=
"id_message"
name
=
"message"
type
=
"text"
/
><
/
td><
/
tr>
默认是按照 <table> 现实输出的,还可以:
>>>
print
f.as_ul()
<li><label
for
=
"id_subject"
>Subject:<
/
label> <
input
id
=
"id_subject"
name
=
"subject"
type
=
"text"
/
><
/
li>
<li><label
for
=
"id_email"
>Email:<
/
label> <
input
id
=
"id_email"
name
=
"email"
type
=
"email"
/
><
/
li>
<li><label
for
=
"id_message"
>Message:<
/
label> <
input
id
=
"id_message"
name
=
"message"
type
=
"text"
/
><
/
li>
>>>
print
f.as_p()
<p><label
for
=
"id_subject"
>Subject:<
/
label> <
input
id
=
"id_subject"
name
=
"subject"
type
=
"text"
/
><
/
p>
<p><label
for
=
"id_email"
>Email:<
/
label> <
input
id
=
"id_email"
name
=
"email"
type
=
"email"
/
><
/
p>
<p><label
for
=
"id_message"
>Message:<
/
label> <
input
id
=
"id_message"
name
=
"message"
type
=
"text"
/
><
/
p>
还可以这样显示
>>>
print
f[
'subject'
]
<
input
id
=
"id_subject"
name
=
"subject"
type
=
"text"
/
>
forms对象做的第二件事是校验数据。现在先添加数据:
>>>
一旦对一个forms对象实体赋值,就可以得到一个绑定的form:
>>> f.is_bound
True
>>>
还可以验证数据是否合法
>>> f.is_valid()
True
>>>
如果合法为True。如果不合法为False。如:如果subject或者,essage为空。f.is_valid()就会返回False
也可以查看每个字段的error
>>> f
=
ContactForm({
'subject'
:
'Hello'
,
'message'
: ''})
>>> f[
'message'
].errors
[u
'This field is required.'
]
>>> f[
'subject'
].errors
[]
>>>
还可以通过errors属性查看错误
>>> f.errors
{
'message'
: [u
'This field is required.'
]}
>>>
如果forms合法,他就有一个cleaned_data属性,将数据转化成Python类型数据,存放在cleaned_data中。
例如:如果是字符串就会被清理成Unicode对象,整数会被清理成Python整数,日期清理成datetime.date型对象
>>> f.is_valid()
True
>>> f.cleaned_data
6. 在视图中使用Form对象
view.py
from
django.shortcuts
import
render
from
contact.forms
import
ContactForm
from
django.http
import
HttpResponseRedirect
from
django.core.mail
import
send_mail
def
contact(request):
if
request.method
=
=
'POST'
:
form
=
ContactForm(request.POST)
if
form.is_valid():
cd
=
form.cleaned_data
send_mail(
cd[
'subject'
],
cd[
'message'
],
)
return
HttpResponseRedirect(
'/contact/thanks/'
)
else
:
form
=
ContactForm()
return
render(request,
'contact_form.html'
, {
'form'
: form})
contact_form.html
<
html
>
<
head
>
<
title
>Contact us</
title
>
</
head
>
<
body
>
<
h1
>Contact us</
h1
>
{% if form.errors %}
<
p
style
=
"color: red;"
>
Please correct the error{{ form.errors|pluralize }} below.
</
p
>
{% endif %}
<
form
action
=
""
method
=
"post"
>
<
table
>
{{ form.as_table }}
</
table
>
{% csrf_token %}
<
input
type
=
"submit"
value
=
"Submit"
>
</
form
>
</
body
>
</
html
>
上面的例子有个缺陷,message这个表单变成了 input type=“text”。
我们可以通过设置widget来修改它:
from
django
import
forms
class
ContactForm(forms.Form):
subject
=
forms.CharField()
email
=
forms.EmailField(required
=
False
)
message
=
forms.CharField(widget
=
forms.Textarea)
还可以设置最大长度
设置max_length
from
django
import
forms
class
ContactForm(forms.Form):
subject
=
forms.CharField(max_length
=
20
)
email
=
forms.EmailField(required
=
False
)
message
=
forms.CharField(widget
=
forms.Textarea)
设置初始值:
在view.py中ContectForm中添加 initial 参数:
from
django.shortcuts
import
render
from
contact.forms
import
ContactForm
from
django.http
import
HttpResponseRedirect
from
django.core.mail
import
send_mail
def
contact(request):
if
request.method
=
=
'POST'
:
form
=
ContactForm(request.POST)
if
form.is_valid():
cd
=
form.cleaned_data
send_mail(
cd[
'subject'
],
cd[
'message'
],
)
return
HttpResponseRedirect(
'/contact/thanks/'
)
else
:
form
=
ContactForm(
initial
=
{
'subject'
:
'AAAAAA'
}
)
return
render(request,
'contact_form.html'
, {
'form'
: form})
注意:默认值与表单传入是有区别的,区别在于,如果仅仅传入默认值,是没有绑定的。
7. 自定义校验规则
例如我们需要添加 message 字段有一个额外的校验,我们就要摘forms类中添加 clean_message() 方法
例子:添加校验 messge中的单词数量(注意不是字母数量,看 split() )要不少于4个.
from
django
import
forms
class
ContactForm(forms.Form):
subject
=
forms.CharField(max_length
=
100
)
email
=
forms.EmailField(required
=
False
)
message
=
forms.CharField(widget
=
forms.Textarea)
def
clean_message(
self
):
message
=
self
.cleaned_data[
'message'
]
num_words
=
len
(message.split())
if
num_words <
4
:
raise
forms.ValidationError(
"Not enough words!"
)
return
message
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK