HTTP 要求
HTTP协议以\"大众要求-回答\"大众的办法事情。客户发送要求时,可以在要求中附加数据。做事器通过解析要求,就可以得到客户传来的数据,并根据URL来供应特定的做事。
GET 方法

我们在之前的项目中创建一个 search.py 文件,用于吸收用户的要求:
/HelloWorld/HelloWorld/search.py 文件代码:
# -- coding: utf-8 --fromdjango.httpimportHttpResponsefromdjango.shortcutsimportrender_to_response# 表单defsearch_form(request): returnrender_to_response('search_form.html')# 吸收要求数据defsearch(request): request.encoding='utf-8'if'q'inrequest.GET: message = '你搜索的内容为: ' + request.GET['q']else: message = '你提交了空表单'returnHttpResponse(message)
在模板目录 templates 中添加 search_form.html 表单:
/HelloWorld/templates/search_form.html 文件代码:
<!DOCTYPEhtml><html><head><metacharset=\"大众utf-8\"大众><title>菜鸟教程(runoob.com)</title></head><body><formaction=\"大众/search\"大众method=\"大众get\公众><inputtype=\"大众text\"大众name=\"大众q\公众><inputtype=\"大众submit\"大众value=\"大众搜索\"大众></form></body></html>
urls.py 规则修正为如下形式:
/HelloWorld/HelloWorld/urls.py 文件代码:
fromdjango.conf.urlsimporturlfrom . importview,testdb,searchurlpatterns = [url(r'^hello$', view.hello), url(r'^testdb$', testdb.testdb), url(r'^search-form$', search.search_form), url(r'^search$', search.search),]
访问地址 http://127.0.0.1:8000/search-form 并搜索,结果如下所示:
POST 方法
上面我们利用了GET方法。视图显示和要求处理分成两个函数处理。
提交数据时更常用POST方法。我们下面利用该方法,并用一个URL和处理函数,同时显示视图和处理要求。
我们在tmplate 创建 post.html:
/HelloWorld/tmplates/post.html 文件代码:
<!DOCTYPEhtml><html><head><metacharset=\"大众utf-8\"大众><title>菜鸟教程(runoob.com)</title></head><body><formaction=\公众/search-post\公众method=\公众post\"大众> {% csrf_token %} <inputtype=\公众text\公众name=\公众q\"大众><inputtype=\"大众submit\公众value=\"大众Submit\"大众></form><p>{{ rlt }}</p></body></html>
在模板的末端,我们增加一个 rlt 暗号,为表格处理结果预留位置。
表格后面还有一个{% csrf_token %}的标签。csrf 全称是 Cross Site Request Forgery。这是Django供应的防止伪装提交要求的功能。POST 方法提交的表格,必须有此标签。
在HelloWorld目录下新建 search2.py 文件并利用 search_post 函数来处理 POST 要求:
/HelloWorld/HelloWorld/search2.py 文件代码:
# -- coding: utf-8 --fromdjango.shortcutsimportrenderfromdjango.views.decoratorsimportcsrf# 吸收POST要求数据defsearch_post(request): ctx ={} ifrequest.POST: ctx['rlt'] = request.POST['q']returnrender(request, \"大众post.html\公众, ctx)
urls.py 规则修正为如下形式:
/HelloWorld/HelloWorld/urls.py 文件代码:
fromdjango.conf.urlsimporturlfrom . importview,testdb,search,search2urlpatterns = [url(r'^hello$', view.hello), url(r'^testdb$', testdb.testdb), url(r'^search-form$', search.search_form), url(r'^search$', search.search), url(r'^search-post$', search2.search_post),]
访问 http://127.0.0.1:8000/search-post 显示结果如下:
完成以上实例后,我们的目录构造为:
HelloWorld|-- HelloWorld| |-- __init__.py| |-- __init__.pyc| |-- search.py| |-- search.pyc| |-- search2.py| |-- search2.pyc| |-- settings.py| |-- settings.pyc| |-- testdb.py| |-- testdb.pyc| |-- urls.py| |-- urls.pyc| |-- view.py| |-- view.pyc| |-- wsgi.py| `-- wsgi.pyc|-- TestModel| |-- __init__.py| |-- __init__.pyc| |-- admin.py| |-- admin.pyc| |-- apps.py| |-- migrations| | |-- 0001_initial.py| | |-- 0001_initial.pyc| | |-- __init__.py| | `-- __init__.pyc| |-- models.py| |-- models.pyc| |-- tests.py| `-- views.py|-- db.sqlite3|-- manage.py`-- templates |-- base.html |-- hello.html |-- post.html `-- search_form.html
Request 工具
每个 view 函数的第一个参数是一个 HttpRequest 工具,就像下面这个 hello() 函数:
from django.http import HttpResponsedef hello(request): return HttpResponse(\"大众Hello world\公众)
HttpRequest工具包含当前要求URL的一些信息:
属性
描述
path
要求页面的全路径,不包括域名—例如, \"大众/hello/\公众。
CONTENT_LENGTH
CONTENT_TYPE
QUERY_STRING: 未解析的原始查询字符串
REMOTE_ADDR: 客户端IP地址
REMOTE_HOST: 客户端主机名
SERVER_NAME: 做事器主机名
SERVER_PORT: 做事器端口
META 中这些头加上前缀HTTP_最为Key, 例如:
HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_LANGUAGE
HTTP_HOST: 客户发送的HTTP主机头信息
HTTP_REFERER: referring页
HTTP_USER_AGENT: 客户真个user-agent字符串
HTTP_X_BENDER: X-Bender头信息
method
要求中利用的HTTP方法的字符串表示。整年夜写表示。例如:
if request.method == 'GET':
do_something()
elif request.method == 'POST':
do_something_else()
GET
包含所有HTTP GET参数的类字典工具。拜会QueryDict 文档。
filename: 上传文件名,用Python字符串表示
content-type: 上传文件的Content type
content: 上传文件的原始内容
把稳:只有在要求方法是POST,并且要求页面中<form>有enctype=\公众multipart/form-data\公众属性时FILES才拥有数据。否则,FILES 是一个空字典。
POST
包含所有HTTP POST参数的类字典工具。拜会QueryDict 文档。
做事器收到空的POST要求的情形也是有可能发生的。也便是说,表单form通过HTTP POST方法提交要求,但是表单中可以没有数据。因此,不能利用语句if request.POST来判断是否利用HTTP POST方法;该当利用if request.method == \公众POST\"大众 (拜会本表的method属性)。
把稳: POST不包括file-upload信息。拜会FILES属性。
REQUEST
为了方便,该属性是POST和GET属性的凑集体,但是有分外性,先查找POST属性,然后再查找GET属性。借鉴PHP's $_REQUEST。
例如,如果GET = {\"大众name\公众: \"大众john\公众} 和POST = {\"大众age\"大众: '34'},则 REQUEST[\公众name\"大众] 的值是\公众john\"大众, REQUEST[\"大众age\"大众]的值是\公众34\公众.
强烈建议利用GET and POST,由于这两个属性更加显式化,写出的代码也更易理解。
COOKIES
包含所有cookies的标准Python字典工具。Keys和values都是字符串。
FILES
包含所有上传文件的类字典工具。FILES中的每个Key都是<input type=\"大众file\公众 name=\"大众\"大众 />标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典工具,包含下面三个Keys:
META
包含所有可用HTTP头部信息的字典。 例如:
user
是一个django.contrib.auth.models.User 工具,代表当前登录的用户。
如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。
你可以通过user的is_authenticated()方法来辨别用户是否登录:
if request.user.is_authenticated(): # Do something for logged-in users.else: # Do something for anonymous users.
只有激活Django中的AuthenticationMiddleware时该属性才可用
session
唯一可读写的属性,代表当前会话的字典工具。只有激活Django中的session支持时该属性才可用。
raw_post_data
原始HTTP POST数据,未解析过。 高等处理时会有用处。
Request工具也有一些有用的方法:
这是我们可以利用字典语法访问HttpRequest工具。
例如,request[\"大众foo\"大众]等同于先request.POST[\公众foo\"大众] 然后 request.GET[\"大众foo\"大众]的操作。
has_key()检讨request.GET or request.POST中是否包含参数指定的Key。get_full_path()返回包含查询字符串的要求路径。例如, \公众/music/bands/the_beatles/?print=true\公众is_secure()如果要求是安全的,返回True,便是说,发出的是HTTPS要求。QueryDict工具
在HttpRequest工具中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情形。
QueryDict实现所有标准的词典方法。还包括一些特有的方法:
__getitem__
和标准字典的处理有一点不同,便是,如果Key对应多个Value,__getitem__()返回末了一个value。
__setitem__
设置参数指定key的value列表(一个Python list)。把稳:它只能在一个mutable QueryDict 工具上被调用(便是通过copy()产生的一个QueryDict工具的拷贝).
get()
如果key对应多个value,get()返回末了一个value。
update()
参数可以是QueryDict,也可以是标准字典。和标准字典的update方法不同,该方法添加字典 items,而不是更换它们:
>>> q = QueryDict('a=1')>>> q = q.copy() # to make it mutable>>> q.update({'a': '2'})>>> q.getlist('a')['1', '2']>>> q['a'] # returns the last['2']
items()
和标准字典的items()方法有一点不同,该方法利用单值逻辑的__getitem__():
>>> q = QueryDict('a=1&a=2&a=3')>>> q.items()[('a', '3')]
values()
和标准字典的values()方法有一点不同,该方法利用单值逻辑的__getitem__():
此外, QueryDict也有一些方法,如下表:
copy()
返回工具的拷贝,内部实现是用Python标准库的copy.deepcopy()。该拷贝是mutable(可变动的) — 便是说,可以变动该拷贝的值。
getlist(key)
返回和参数key对应的所有值,作为一个Python list返回。如果key不存在,则返回空list。 It's guaranteed to return a list of some sort..
setlist(key,list_)
设置key的值为list_ (unlike __setitem__()).
appendlist(key,item)
添加item到和key关联的内部list.
setlistdefault(key,list)
和setdefault有一点不同,它接管list而不是单个value作为参数。
lists()
和items()有一点不同, 它会返回key的所有值,作为一个list, 例如:
>>> q =QueryDict('a=1&a=2&a=3')>>> q.lists()[('a',['1','2','3'])]
urlencode()
返回一个以查询字符串格式进行格式化后的字符串(e.g., \公众a=2&b=3&b=5\"大众).