一、HttpRequest对象的一些属性或方法
- request.path,The full path, not including the domain but including the leading slash,例如:"/hello/"
- request.get_host(),The host (i.e., the “domain,” in common parlance).例如:"127.0.0.1:8000" or"www.example.com"
- request.get_full_path(),The path, plus a query string (if available),例如:"/hello/?print=true"
- request.is_secure(),True if the request was made via HTTPS. Otherwise, False。例如:True or False
关于请求的其他信息request.META是一个字典,包含了所有HTTP头部信息,一些常见的keys如下:
- HTTP_REFERER – The referring URL, if any. (Note the misspelling of REFERER.)
- HTTP_USER_AGENT – The user’s browser’s user-agent string, if any. This looks something like:"Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17".
- REMOTE_ADDR – The IP address of the client, e.g., "12.345.67.89". (If the request has passed through any proxies, then this might be a comma-separated list of IP addresses, e.g., "12.345.67.89,23.456.78.90".)
注意:当不知道字典中是否含有一个键时,最好用get方法,因为META是一个字典,获取一个不存在的键会返回一个异常。例如:
ua = request.META.get('HTTP_USER_AGENT', 'unknown')
request.GET和request.POST是两个类似于字典的对象,他们都有get(), keys() and values() 方法,也可以迭代for key in request.GET,
POST数据基本上是都是来自于表单提交的数据,GET可以是表单也可以是网页的URL
2、根据学生ID搜索学生信息的简单例子:
models是
class StudentInfo(models.Model): name = models.CharField(max_length = 50,default=""); studentID = models.CharField(max_length=12,default=""); sex = models.CharField(max_length = 5,default=""); age = models.IntegerField(default=0); address = models.TextField(default="");
template文件夹里存放template文件,searchBase.html文件如下:
{ % block title %}{% endblock %} { % block search %} { % endblock %}
{ % block footer %}©2016 Allen
{ % endblock %}
searchStudentInfo.html文件内容如下:
1 {% extends "searchBase.html" %} 2 3 {% block title %}get student infomation{% endblock %} 4 5 {% block search %} 6根据ID搜索学生信息
78 1213 {% endblock %}
在视图文件中定义搜索id的视图,SearchForm函数
1 def SearchForm(request):2 return render(request, "searchStudentInfo.html")
在urls文件中定义路由
url(r'^searchform/$', views.SearchForm),
此时还不能正常工作,因为没有写搜索的响应函数。当然可以看一下效果
接下来为其添加响应函数,views.py
1 def SearchStudentInfo(request):2 if 'q' in request.POST:3 searchInfo = "you searched %s"%request.POST['q'];4 else:5 searchInfo = "you submitted an empty form"6 return HttpResponse(searchInfo);
添加路由
url(r'^search/$', views.SearchStudentInfo),
此时可以正常工作。
3、将查询结果做成模版进行显示
创建显示结果模版searchResult.html代码如下:
1 {% extends "searchBase.html"%} 2 3 {% block title %}search result{% endblock %} 4 5 {% block search %} 6You searched for: { { query }}
7 {% if students %} 8Found {
{students|length}} students 9
姓名 | 12学号 | 13性别 | 14年龄 | 15地址 | 16
{ { student.name }} | 21{ { student.studentID }} | 22{ { student.sex }} | 23{ { student.age }} | 24{ { student.address }} | 25 26
not found student where studentID = {
{ query }}31 {% endif %}32 {% endblock %}修改视图函数views.py
1 def SearchStudentInfo(request): 2 if 'q' in request.GET and request.GET['q']: 3 stu = StudentInfo.objects.filter(studentID=request.GET['q']) 4 if stu: 5 context = { 'query':request.GET['q'],'students':stu} 6 return render(request, 'searchResult.html', context) 7 else: 8 return HttpResponse("not found information"); 9 10 else:11 searchInfo = "you submitted an empty form"12 return HttpResponse(searchInfo);
此时可以运行一下查看结果,效果如下:
二、对这个表单进行改进
对网址http://127.0.0.1:8888/student/search/进行访问,有三种可能情况
- 访问页面,此时没有‘q’参数在GET中
- 点击提交按钮,‘q’在GET中,但是搜索框中没有搜索内容。
- 点击提交按钮,‘q’在GET中,搜索框中有搜索内容。
对于第一种情况我们不应该显示出错误信息,第二种情况应该显示出错信息,第三种情况应当进入数据库进行查询。为了更专业一点,当没有输入数据提交时,应当返回上一个查询框,而不是返回一个字符串。
需要修改的地方有 1、视图函数 2、在搜索模版中加入判断的变量error
views.py
1 def SearchStudentInfo(request): 2 error = False; 3 if 'q' in request.GET : 4 if not request.GET['q']: 5 error=True; 6 else: 7 stu = StudentInfo.objects.filter(studentID=request.GET['q']) 8 context = { 'query':request.GET['q'],'students':stu} 9 return render(request, 'searchResult.html', context)10 11 return render(request, 'searchStudentInfo.html', { 'error':error});
searchStudentInfo.html
1 {% extends "searchBase.html" %} 2 3 {% block title %}search student infomation{% endblock %} 4 5 {% block search %} 6根据ID搜索学生信息
78 {% if error %} 916 {% endblock %}Please submit a search term.
10 {% endif %}11 15
2、
<form action="" method="get">
当 action=""表示提交表单时,将向当前的url提交。3、当表单是通过post提交过后,最好在处理过提交上来的数据后使用HttpResponseRedirect,以防止产生一些麻烦,比如:多次提交、刷新提交。可能会在后台数据库中产生多个相同记录。
from django.http import HttpResponseRedirect
三、form类,是django带来的处理form的一些类库,可以放在任意位置,不过一般将其单独成一个文件forms.py,和views.py放在同一个文件夹
首先写一个forms.py文件,ContactForm类。
from django import formsclass ContactForm(forms.Form): subject = forms.CharField(); email = forms.EmailField(required = False); message = forms.CharField();
注意:默认情况下form类的数据是必须的,可以通过参数来修改。required=False
form类对象含有一些方法,比如:as_ul(),将每项数据li列出来,as_p():将每项数据生成段落。
from studentInfo.forms import ContactFormc=ContactForm()print c.as_ul()
也可以显示某一列
>>> print c['subject'] >>> print c['message']
2、检查有效性,通过一个字典将forms类初始化。对象一旦初始化数据后,就是一个“bound”form。
f = ContactForm({ 'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})f.is_boundTrue
检查有效性的函数是is_valid().如果数据有效,可以通过clean()方法,返回一个没有错误的数据字典。
>>> f = ContactForm({ 'subject': 'Hello', 'message': 'Nice site!'})>>> f.is_valid()True>>> f = ContactForm({ 'subject': 'Hello', 'message': ''})>>> f.is_valid()False
也可以获得指定域的错误信息,通过errors属性。如果有错,则会显示出来;如果没有,则是一个空的列表。
>>> f = ContactForm({ 'subject': 'Hello', 'message': ''})>>> f['message'].errors[u'This field is required.']>>> f['subject'].errors[]>>> f['email'].errors[]
每一个绑定数据的对象都有一个errors属性,是一个将域和错误信息列表映射起来。
如果form对象的数据是有效的,则可以使用cleaned_data属性。他会将form对象转换成合适的python数据类型
>>> f = ContactForm({ 'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'}) >>> f.is_valid() True >>> f.cleaned_data {'message': u'Nice site!', 'email': u'adrian@example.com', 'subject': u'Hello'} 3、在views文件中使用forms对象,例子如下:
def ContactUs(request): if request.method =="POST": form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data; print cd['subject'],cd['message'],cd.get('email', 'noreply@example.com') return HttpResponseRedirect('/student/contact/thanks/') else: form = ContactForm(); return render(request, "contactus.html", { 'form':form})
contactus.html模版文件如下:
Contact us Contact us
{ % if form.errors %}Please correct the error{
{ form.errors|pluralize }} below. { % endif %}
运行结果
现在message输入框形式本应该是textarea形式,却是text line形式,可以通过修改forms类的参数来改变展现形式。
forms.py文件
from django import formsclass ContactForm(forms.Form): subject = forms.CharField(); email = forms.EmailField(required = False); message = forms.CharField(widget=forms.Textarea);
field类表示有效逻辑,widget表示展现形式。max_length表示可以输入的最大字符数,min_length表示最少字符数。限定charfield。
4、定制forms规则,当需要一个特别的有效性规则、并且需要经常使用,可以考虑定制一个规则。在forms类中实现方法
比如不能使message输入的单词数少于4个,可以在类中写一个方法
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
注意:它是以clean_开头,以字段名称结束的方法,他将在校验时调用。
我们需要在最后将校验的字段返回,否则None将会被返回,原始数据丢失。
5、指定标签
HTML表单中自动生成的标签默认是按照规则生成的:用空格代替下划线,首字母大写。如email的标签是"Email"。可以使用
label='Your e-mail address'例如:email = forms.EmailField(required=False, label='Your e-mail address' )
6、定制form设计
为了更加精确的控制显示效果,我们可以通过{
{form.字段名}}进行单独的渲染三、表单的一些高级用法 1 表单继承 Form的子类还可以被继承,也可以多重继承,如果有些变量不想在子类中使用,可以使用Meta类中的fields或exclude来限制可用变量
class Person(forms.Form): first =forms.CharField() last = forms.CharField() middle = forms.CharField()class AgedPerson(Person): age = forms.IntegerField() class Meta: exclude=('middle',)
2 填写表单
用request.POST来填充表单时,如果含有额外数据,form类会自动无视那些和他们定义的变量没关系的输入。