Django的HttpRequest和HttpResponse对象详解
本文研究的主要是Django的HttpRequest和HttpResponse对象的相关内容,具体如下。
请求一张页面时,Django把请求的metadata数据包装成一个HttpRequest对象,然后Django加载合适的view方法,把这个HttpRequest对象作为第一个参数传给view方法。任何view方法都应该返回一个HttpResponse对象。
我们在本书中大量使用这两个对象;本附录详细解释HttpRequest和HttpResponse对象。
HttpRequest
HttpRequest代表一个来自uesr-agent的HTTP请求。
大多重要的请求信息都是作为HttpRequest对象的属性出现(seeTableH-1).除了session外,其他所有属性都是只读的。
Description
path
请求页面的全路径,不包括域名—例如,"/music/bands/the_beatles/"。
method
请求中使用的HTTP方法的字符串表示。全大写表示。例如:
if request.method == 'GET':
GET
包含所有HTTPGET参数的类字典对象。参见QueryDict文档。
POST
包含所有HTTPPOST参数的类字典对象。参见QueryDict文档。
服务器收到空的POST请求的情况也是有可能发生的。也就是说,表单form通过HTTPPOST方法提交请求,但是表单中可以没有数据。因此,不能使用语句ifrequest.POST来判断是否使用HTTPPOST方法;应该使用ifrequest.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".
强烈建议使用GETandPOST,因为这两个属性更加显式化,写出的代码也更易理解。
COOKIES
包含所有cookies的标准Python字典对象。Keys和values都是字符串。参见第12章,有关于cookies更详细的讲解。
FILES
包含所有上传文件的类字典对象。FILES中的每个Key都是
- filename:上传文件名,用Python字符串表示
- content-type:上传文件的Contenttype
- content:上传文件的原始内容
注意:只有在请求方法是POST,并且请求页面中
META
包含所有可用HTTP头部信息的字典。例如:
- 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头信息
user
是一个django.contrib.auth.models.User对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登录:
if request.user.is_authenticated():
只有激活Django中的AuthenticationMiddleware时该属性才可用
关于认证和用户的更详细讲解,参见第12章。
session
唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。参见第12章。
raw_post_data
原始HTTPPOST数据,未解析过。高级处理时会有用处。
Request对象也有一些有用的方法,见TableH-2:
QueryDict对象
在HttpRequest对象中,GET和POST属性是django.http.QueryDict类的实例。QueryDict类似字典的自定义类,用来处理单键对应多值的情况。因为一些HTMLform元素,例如,
QueryDict对象是immutable(不可更改的),除非创建它们的copy()。这意味着我们不能直接改变request.POSTandrequest.GET的属性。
QueryDict实现所有标准的字典方法。还包括一些特有的方法,见TableH-3.
TableH-3.HowQueryDictsDifferfromStandardDictionaries.
Method
DifferencesfromStandarddictImplementation
__getitem__
和标准字典的处理有一点不同,就是,如果Key对应多个Value,__getitem__()返回最后一个value。
__setitem__
设置参数指定key的value列表(一个Pythonlist)。注意:它只能在一个mutableQueryDict对象上被调用(就是通过copy()产生的一个QueryDict对象的拷贝).
get()
如果key对应多个value,get()返回最后一个value。
update()
参数可以是QueryDict,也可以是标准字典。和标准字典的update方法不同,该方法添加字典items,而不是替换它们:
>>> q = QueryDict('a=1')
['1', '2']
items()
和标准字典的items()方法有一点不同,该方法使用单值逻辑的__getitem__():
>>> q = QueryDict('a=1&a=2&a=3')
values()
和标准字典的values()方法有一点不同,该方法使用单值逻辑的__getitem__():
此外,QueryDict也有一些方法,见TableH-4.
Method
Description
copy()
返回对象的拷贝,内部实现是用Python标准库的copy.deepcopy()。该拷贝是mutable(可更改的)—就是说,可以更改该拷贝的值。
getlist(key)
返回和参数key对应的所有值,作为一个Pythonlist返回。如果key不存在,则返回空list。It'sguaranteedtoreturnalistofsomesort..
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')
urlencode()
返回一个以查询字符串格式进行格式化后的字符串(e.g.,"a=2&b=3&b=5").
ACompleteExample
例如,下面是一个HTMLform:
TheBeatles TheWho TheZombies
如果用户在your_name域中输入"JohnSmith",同时在多选框中选择了“TheBeatles”和“TheZombies”,下面是Django请求对象的内容:
>>>request.GET{} >>>request.POST {'your_name':['JohnSmith'],'bands':['beatles','zombies']} >>>request.POST['your_name'] 'JohnSmith' >>>request.POST['bands'] 'zombies' >>>request.POST.getlist('bands') ['beatles','zombies'] >>>request.POST.get('your_name','Adrian') 'JohnSmith' >>>request.POST.get('nonexistent_field','NowhereMan') 'NowhereMan'
HttpResponse
对于HttpRequest对象来说,是由Django自动创建,但是,HttpResponse对象就必须我们自己创建。每个View方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse。
构造HttpResponses
一般地,你可以通过给HttpResponse的构造函数传递字符串表示的页面内容来构造HttpResponse对象:
>>>response=HttpResponse("Here'sthetextoftheWebpage.") >>>response=HttpResponse("Textonly,please.",mimetype="text/plain")
但是如果想要增量添加内容,你可以把response当作filelike对象使用:
>>>response=HttpResponse() >>>response.write("Here'sthetextoftheWebpage.
") >>>response.write("Here'sanotherparagraph.
")
也可以给HttpResponse传递一个iterator作为参数,而不用传递硬编码字符串。如果你使用这种技术,下面是需要注意的一些事项:
·iterator应该返回字符串.
·如果HttpResponse使用iterator进行初始化,就不能把HttpResponse实例作为filelike对象使用。这样做将会抛出异常。
最后,再说明一下,HttpResponse实现了write()方法,可以在任何需要filelike对象的地方使用HttpResponse对象。参见第11章,有一些例子。
设置Headers
你可以使用字典语法添加,删除headers:
>>>response=HttpResponse() >>>response['X-DJANGO']="It'sthebest." >>>delresponse['X-PHP'] >>>response['X-DJANGO'] "It'sthebest."
你也可以使用has_header(header)方法检测某个header是否存在。
不要手动设置Cookieheaders;具体的做法,参见第12章,有关于怎样在Django中处理cookies的详细讲解。
HttpResponse子类
Django包含很多HttpResponse子类,用来处理不同的HTTP响应类型(见TableH-5).和HttpResponse一样,这些子类在django.http中.
TableH-5.HttpResponseSubclasses Class Description HttpResponseRedirect 构造函数接受单个参数:重定向到的URL。可以是全URL(e.g.,'http://search.yahoo.com/')或者相对URL(e.g.,'/search/').注意:这将返回HTTP状态码302。 HttpResponsePermanentRedirect 同HttpResponseRedirect一样,但是返回永久重定向(HTTP状态码301)。 HttpResponseNotModified 构造函数不需要参数。Usethistodesignatethatapagehasn'tbeenmodifiedsincetheuser'slastrequest. HttpResponseBadRequest 返回400statuscode。 HttpResponseNotFound 返回404statuscode. HttpResponseForbidden 返回403statuscode. HttpResponseNotAllowed 返回405statuscode.它需要一个必须的参数:一个允许的方法的list(e.g.,['GET','POST']). HttpResponseGone 返回410statuscode. HttpResponseServerError 返回500statuscode.
当然,你也可以自己定义不包含在上表中的HttpResponse子类。
返回Errors
在Django中返回HTTP错误码是很容易的。上面介绍了HttpResponseNotFound,HttpResponseForbidden,HttpResponseServerError等一些子类。View方法中返回这些子类的实例就OK了,例如:
defmy_view(request): #... iffoo: returnHttpResponseNotFound('Pagenotfound
') else: returnHttpResponse('Pagewasfound
')
当返回HttpResponseNotFound时,你需要定义错误页面的HTML:
returnHttpResponseNotFound('
Pagenotfound
')因为404错误是最常使用的HTTP错误,有一个更方便的方法处理它。
为了方便,而且整个站点有一致的404错误页面也是友好的,Django提供一个Http404异常类。如果在一个View方法中抛出Http404,Django将会捕获它并且返回标准错误页面,同时返回错误码404。
fromdjango.httpimportHttp404 defdetail(request,poll_id): try: p=Poll.objects.get(pk=poll_id) exceptPoll.DoesNotExist: raiseHttp404 returnrender_to_response('polls/detail.html',{'poll':p})
为了使用Http404异常,你需要创建一个模板文件。当异常抛出时,就会显示该模板文件。该模板文件的文件名是404.html,在模板根目录下创建。
自定义404(NotFound)View方法
当抛出Http404异常时,Django会加载一个特殊的view方法处理404错误。默认地,它是django.views.defaults.page_not_found,负责加载和渲染404.html模板文件。
这意味着我们必须在模板根目录定义404.html模板文件,该模板文件应用于所有的404异常。
该page_not_foundview方法应该可以应对几乎99%的WebApp,但是如果想要重载该view方法时,你可以在URLConf文件中指定handler404为自定义的404errprview方法,像这样:
fromdjango.conf.urls.defaultsimport* urlpatterns=patterns('', ... ) handler404='mysite.views.my_custom_404_view'
Django就是通过在URLConf文件中查找handler404来决定404view方法的。默认地,URLconfs包含下面一行代码:
fromdjango.conf.urls.defaultsimport*
在django/conf/urls/defaults.py模块中,handler404赋值为'django.views.defaults.page_not_found'。
注意:
·如果请求URL没有和Django的URLConf文件中的任何一个正则表示式匹配,404view方法就会被调用。
·如果没有定义自己的404view—使用默认地404view,你仍然有一个工作要做:在模板根目录创建404.html模板文件。默认地404view将使用该模板处理所有404错误。
·如果DEBUG设置为True(在setting模块中),404view方法不会被使用,取而代之的是,traceback信息。
自定义500(ServerError)View方法
同样地,当view代码发生运行时错误时,Django也会产生特殊行为。如果view方法产生异常,Django将会调用默认地view方法django.views.defaults.server_error,该方法加载渲染500.html模板文件。
这意味着我们必须在模板根目录定义500.html模板文件,该模板文件应用于所有的服务器错误。
该server_errorview方法应该可以应对几乎99%的WebApp,但是如果想要重载该view方法时,你可以在URLConf文件中指定handler500为自定义的servererrorview方法,像这样:
fromdjango.conf.urls.defaultsimport* urlpatterns=patterns('', ... ) handler500='mysite.views.my_custom_error_view'
翻译文章来源(Django官网文档):https://docs.djangoproject.com/en/1.9/ref/request-response/#django.http.HttpRequest
其中进行了一些整理。
总结
以上就是本文关于Django的HttpRequest和HttpResponse对象详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!