Django之HttpRequest和HttpResponse

Django 是围绕着 Request 与 response 进行处理,也就是无外乎“求”与“应”。当请求一个页面时,Django 把请求的 metadata 数据包装成一个 HttpRequest 对象,然后 Django 加载合适的 view 方法,把这个 HttpRequest 对象作为第一个参数传给 view 方法。任何 view 方法都应该返回一个 HttpResponse 对象。

HttpRequest

每当一个用户请求发送过来,Django将HTTP数据包中的相关内容,打包成为一个HttpRequest对象,并传递给每个视图函数作为第一位置参数,也就是request,供我们调用。
HttpRequest对象中包含了非常多的重要的信息和数据,应该熟练掌握它。
类定义:class HttpRequest[source]

一、HttpRequest属性

HttpRequest对象的大部分属性是只读的。
1. HttpRequest.scheme
字符串类型,表示请求的协议种类,'http'或'https'。
2. HttpRequest.body
bytes类型,表示原始HTTP请求的正文。它对于处理非HTML形式的数据非常有用:二进制图像、XML等。如果要处理常规的表单数据,应该使用HttpRequest.POST。
还可以使用类似读写文件的方式从HttpRequest中读取数据,参见HttpRequest.read()。
3. HttpRequest.path
字符串类型,表示当前请求页面的完整路径,但是不包括协议名和域名。例如:"/music/bands/the_beatles/"。这个属性,常被用于我们进行某项操作时,如果不通过,返回用户先前浏览的页面。非常有用!
4. HttpRequest.path_info
在某些Web服务器配置下,主机名后的URL部分被分成脚本前缀部分和路径信息部分。path_info 属性将始终包含路径信息部分,不论使用的Web服务器是什么。使用它代替path可以让代码在测试和开发环境中更容易地切换。
例如,如果应用的WSGIScriptAlias设置为/minfo,那么HttpRequest.path等于/music/bands/the_beatles/ ,而HttpRequest.path_info为/minfo/music/bands/the_beatles/。
5. HttpRequest.method
字符串类型,表示请求使用的HTTP方法。默认为大写。 像这样:
if request.method == 'GET':
    do_something()
elif request.method == 'POST':
    do_something_else()
通过这个属性来判断请求的方法,然后根据请求的方法不同,在视图中执行不同的代码。
6. HttpRequest.encoding
字符串类型,表示提交的数据的编码方式(如果为None 则表示使用DEFAULT_CHARSET设置)。 这个属性是可写的,可以通过修改它来改变表单数据的编码。任何随后的属性访问(例如GET或POST)将使用新的编码方式。
7. HttpRequest.content_type
Django1.10中新增。表示从CONTENT_TYPE头解析的请求的MIME类型。
8. HttpRequest.content_params
Django 1.10中新增。包含在CONTENT_TYPE标题中的键/值参数字典。
9 HttpRequest.GET
一个类似于字典的对象,包含GET请求中的所有参数。 详情参考QueryDict文档。
10. HttpRequest.POST
一个包含所有POST请求的参数,以及包含表单数据的字典。 详情请参考QueryDict文档。 如果需要访问请求中的原始或非表单数据,可以使用HttpRequest.body属性。
注意:请使用if request.method == "POST"来判断一个请求是否POST类型,而不要使用if request.POST。
POST中不包含上传文件的数据。
11. HttpRequest.COOKIES
包含所有Cookie信息的字典。 键和值都为字符串。可以类似字典类型的方式,在cookie中读写数据,但是注意cookie是不安全的,因此,不要写敏感重要的信息。
12. HttpRequest.FILES
一个类似于字典的对象,包含所有上传的文件数据。 FILES中的每个键为中的name属性值。 FILES中的每个值是一个UploadedFile。
要在Django中实现文件上传,就要靠这个属性!
如果请求方法是POST且请求的

中带有enctype="multipart/form-data"属性,那么FILES将包含上传的文件的数据。 否则,FILES将为一个空的类似于字典的对象,属于被忽略、无用的情形。
13. HttpRequest.META
包含所有HTTP头部信息的字典。 可用的头部信息取决于客户端和服务器,下面是一些示例:
    CONTENT_LENGTH —— 请求正文的长度(以字符串计)。
    CONTENT_TYPE —— 请求正文的MIME类型。
    HTTP_ACCEPT —— 可接收的响应Content-Type。
    HTTP_ACCEPT_ENCODING —— 可接收的响应编码类型。
    HTTP_ACCEPT_LANGUAGE —— 可接收的响应语言种类。
    HTTP_HOST —— 客服端发送的Host头部。
    HTTP_REFERER —— Referring页面。
    HTTP_USER_AGENT —— 客户端的user-agent字符串。
    QUERY_STRING —— 查询字符串。
    REMOTE_ADDR —— 客户端的IP地址。想要获取客户端的ip信息,就在这里!
    REMOTE_HOST —— 客户端的主机名。
    REMOTE_USER —— 服务器认证后的用户,如果可用。
    REQUEST_METHOD —— 表示请求方法的字符串,例如"GET" 或"POST"。
    SERVER_NAME —— 服务器的主机名。
    SERVER_PORT —— 服务器的端口(字符串)。
从上面可以看到,除CONTENT_LENGTH和CONTENT_TYPE之外,请求中的任何HTTP头部键转换为META键时,都会将所有字母大写并将连接符替换为下划线最后加上HTTP_前缀。所以,一个叫做X-Bender的头部将转换成META中的HTTP_X_BENDER键。
13. HttpRequest.resolver_match
代表一个已解析的URL的ResolverMatch实例。

二、可自定义的属性

Django不会自动设置下面这些属性,而是由你自己在应用程序中设置并使用它们。
1. HttpRequest.current_app
表示当前app的名字。url模板标签将使用其值作为reverse()方法的current_app参数。
2. HttpRequest.urlconf
设置当前请求的根URLconf,用于指定不同的url路由进入口,这将覆盖settings中的ROOT_URLCONF设置。
将它的值修改为None,可以恢复使用ROOT_URLCONF设置。

三、由中间件设置的属性

Django的contrib应用中包含的一些中间件会在请求上设置属性。
1. HttpRequest.session
SessionMiddleware中间件:一个可读写的,类似字典的对象,表示当前会话。我们要保存用户状态,回话过程等等,靠的就是这个中间件和这个属性。
2. HttpRequest.site
CurrentSiteMiddleware中间件:get_current_site()方法返回的Site或RequestSite的实例,代表当前站点是哪个。
Django是支持多站点的,如果你同时上线了几个站点,就需要为每个站点设置一个站点id。
3. HttpRequest.user
AuthenticationMiddleware中间件:表示当前登录的用户的AUTH_USER_MODEL的实例,这个模型是Django内置的Auth模块下的User模型。如果用户当前未登录,则user将被设置为AnonymousUser的实例。
可以使用is_authenticated方法判断当前用户是否合法用户,如下所示:

if request.user.is_authenticated:
    ... # Do something for logged-in users.
else:
    ... # Do something for anonymous users.

四、方法

1. HttpRequest.get_host()[source]
根据HTTP_X_FORWARDED_HOST和HTTP_HOST头部信息获取请求的原始主机。 如果这两个头部没有提供相应的值,则使用SERVER_NAME和SERVER_PORT。
例如:"127.0.0.1:8000"
注:当主机位于多个代理的后面,get_host()方法将会失败。解决办法之一是使用中间件重写代理的头部,如下面的例子:

from django.utils.deprecation import MiddlewareMixin
class MultipleProxyMiddleware(MiddlewareMixin):
    FORWARDED_FOR_FIELDS = [
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED_HOST',
        'HTTP_X_FORWARDED_SERVER',
    ]
    def process_request(self, request):
        """
        Rewrites the proxy headers so that only the most
        recent proxy is used.
        """
        for field in self.FORWARDED_FOR_FIELDS:
            if field in request.META:
                if ',' in request.META[field]:
                    parts = request.META[field].split(',')
                    request.META[field] = parts[-1].strip()

2. HttpRequest.get_port()[source]
使用META中HTTP_X_FORWARDED_PORT和SERVER_PORT的信息返回请求的始发端口。
3. HttpRequest.get_full_path()[source]
返回包含完整参数列表的path。例如:/music/bands/the_beatles/?print=true
4. HttpRequest.build_absolute_uri(location)[source]
返回location的绝对URI形式。 如果location没有提供,则使用request.get_full_path()的值。
例如:"https://example.com/music/bands/the_beatles/?print=true"
注:不鼓励在同一站点混合部署HTTP和HTTPS,如果需要将用户重定向到HTTPS,最好使用Web服务器将所有HTTP流量重定向到HTTPS。
5. HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)[source]
从已签名的Cookie中获取值,如果签名不合法则返回django.core.signing.BadSignature。
可选参数salt用来为密码加盐,提高安全系数。 max_age参数用于检查Cookie对应的时间戳是否超时。
范例:

>>> request.get_signed_cookie('name')
'Tony'
>>> request.get_signed_cookie('name', salt='name-salt')
'Tony' # assuming cookie was set using the same salt
>>> request.get_signed_cookie('non-existing-cookie')
...
KeyError: 'non-existing-cookie'
>>> request.get_signed_cookie('non-existing-cookie', False)
False
>>> request.get_signed_cookie('cookie-that-was-tampered-with')
...
BadSignature: ...
>>> request.get_signed_cookie('name', max_age=60)
...
SignatureExpired: Signature age 1677.3839159 > 60 seconds
>>> request.get_signed_cookie('name', False, max_age=60)
False

6. HttpRequest.is_secure()[source]
如果使用的是Https,则返回True,表示连接是安全的。
7. HttpRequest.is_ajax()[source]
如果请求是通过XMLHttpRequest生成的,则返回True。
这个方法的作用就是判断,当前请求是否通过ajax机制发送过来的。
8. HttpRequest.read(size=None)[source]
9. HttpRequest.readline()[source]
10. HttpRequest.readlines()[source]
11. HttpRequest.xreadlines()[source]
12. HttpRequest.iter()
上面的几个方法都是从HttpRequest实例读取文件数据的方法。
可以将HttpRequest实例直接传递到XML解析器,例如ElementTree:

import xml.etree.ElementTree as ET
for element in ET.iterparse(request):
    process(element)

HttpResponse

类定义:class HttpResponse[source]
HttpResponse类定义在django.http模块中。
HttpRequest对象由Django自动创建,而HttpResponse对象则由程序员手动创建.
我们编写的每个视图都要实例化、填充和返回一个HttpResponse对象。也就是函数的return值。

一、使用方法

1. 传递一个字符串
最简单的方式是传递一个字符串作为页面的内容到HttpResponse构造函数,并返回给用户:
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")
可以将response看做一个类文件对象,使用wirte()方法不断地往里面增加内容。
>>> response = HttpResponse()
>>> response.write("

Here's the text of the Web page.

")
>>> response.write("

Here's another paragraph.

")
2. 传递可迭代对象
HttpResponse会立即处理这个迭代器,并把它的内容存成字符串,最后废弃这个迭代器。比如文件在读取后,会立刻调用close()方法,关闭文件。
3. 设置头部字段
可以把HttpResponse对象当作一个字典一样,在其中增加和删除头部字段。
>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']

注意!与字典不同的是,如果要删除的头部字段如果不存在,del不会抛出KeyError异常。
HTTP的头部字段中不能包含换行。所以如果我们提供的头部字段值包含换行符(CR或者LF),将会抛出BadHeaderError异常。
4. 告诉浏览器将响应视为文件附件
让浏览器以文件附件的形式处理响应, 需要声明content_type类型和设置Content-Disposition头信息。 例如,给浏览器返回一个微软电子表格:
>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'

二、属性

1. HttpResponse.content
响应的内容。bytes类型。
2. HttpResponse.charset
编码的字符集。 如果没指定,将会从content_type中解析出来。
3. HttpResponse.status_code
响应的状态码,比如200。
4. HttpResponse.reason_phrase
响应的HTTP原因短语。 使用标准原因短语。
除非明确设置,否则reason_phrase由status_code的值决定。
5. HttpResponse.streaming
这个属性的值总是False。由于这个属性的存在,使得中间件能够区别对待流式响应和常规响应。
6. HttpResponse.closed
如果响应已关闭,那么这个属性的值为True。

三、 方法

1. HttpResponse.init(content='', content_type=None, status=200, reason=None, charset=None)[source]
响应的实例化方法。使用content参数和content-type实例化一个HttpResponse对象。
content应该是一个迭代器或者字符串。如果是迭代器,这个迭代期返回的应是一串字符串,并且这些字符串连接起来形成response的内容。 如果不是迭代器或者字符串,那么在其被接收的时候将转换成字符串。
content_type是可选地,用于填充HTTP的Content-Type头部。如果未指定,默认情况下由DEFAULT_CONTENT_TYPE和DEFAULT_CHARSET设置组成:text/html; charset=utf-8。
status是响应的状态码。reason是HTTP响应短语。charset是编码方式。
2. HttpResponse.has_header(header)
检查头部中是否有给定的名称(不区分大小写),返回True或 False。
3. HttpResponse.setdefault(header, value)
设置一个头部,除非该头部已经设置过了。
4. HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
设置一个Cookie。 参数与Python标准库中的Morsel.Cookie对象相同。
max_age: 生存周期,以秒为单位。
expires:到期时间。
domain: 用于设置跨域的Cookie。例如domain=".lawrence.com"将设置一个www.lawrence.com、blogs.lawrence.com和calendars.lawrence.com都可读的Cookie。 否则,Cookie将只能被设置它的域读取。
如果你想阻止客服端的JavaScript访问Cookie,可以设置httponly=True。
5. HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)
与set_cookie()类似,但是在设置之前将对cookie进行加密签名。通常与HttpRequest.get_signed_cookie()一起使用。
6. HttpResponse.delete_cookie(key, path='/', domain=None)
删除Cookie中指定的key。
由于Cookie的工作方式,path和domain应该与set_cookie()中使用的值相同,否则Cookie不会删掉。
7. HttpResponse.write(content)[source]
将HttpResponse实例看作类似文件的对象,往里面添加内容。
8. HttpResponse.flush()
清空HttpResponse实例的内容。
9. HttpResponse.tell()[source]
将HttpResponse实例看作类似文件的对象,移动位置指针。
10. HttpResponse.getvalue()[source]
返回HttpResponse.content的值。 此方法将HttpResponse实例看作是一个类似流的对象。
11. HttpResponse.readable()
Django1.10中的新功能,值始终为False。
12. HttpResponse.seekable()
Django1.10中的新功能,值始终为False。
13. HttpResponse.writable()[source]
Django1.10中的新功能,值始终为True。
14. HttpResponse.writelines(lines)[source]
将一个包含行的列表写入响应对象中。 不添加分行符。

四、HttpResponse的子类

Django包含了一系列的HttpResponse衍生类(子类),用来处理不同类型的HTTP响应。与HttpResponse相同, 这些衍生类存在于django.http之中。

五、JsonResponse类

class JsonResponse(data,encoder = DjangoJSONEncoder,safe = True,json_dumps_params = None ,** kwargs)[source]
JsonResponse是HttpResponse的一个子类,是Django提供的用于创建JSON编码类型响应的快捷类。
它从父类继承大部分行为,并具有以下不同点:
它的默认Content-Type头部设置为application/json。
它的第一个参数data,通常应该为一个字典数据类型。 如果safe参数设置为False,则可以是任何可JSON 序列化的对象。
encoder默认为django.core.serializers.json.DjangoJSONEncoder,用于序列化数据。
布尔类型参数safe默认为True。 如果设置为False,可以传递任何对象进行序列化(否则,只允许dict 实例)。
典型的用法如下:

>>> from django.http import JsonResponse
>>> response = JsonResponse({'foo': 'bar'})
>>> response.content
b'{"foo": "bar"}'

若要序列化非dict对象,必须设置safe参数为False:
>>> response = JsonResponse([1, 2, 3], safe=False)
如果不传递safe=False,将抛出一个TypeError。
如果你需要使用不同的JSON 编码器类,可以传递encoder参数给构造函数:
>>> response = JsonResponse(data, encoder=MyJSONEncoder)

1.HttpResponse返回的都是字符串,如果要传字典和列表需要序列化处理
def t_test(request):
li=[1,2,3]
dic={“k1”:jerd,”k2”:”dandan”}
import json
str_li=json.dumps(li)
str_dic = json.dumps(dic)
return HttpResponse(str_li,str_dic) #只能返回一个字符串。显示不出来
2.使用JsonResponse
from django.http import JsonResponse
def t_test(request):
dic={“k1”:jerd,”k2”:”dandan”}
return JsonResponse(dic)
默认只能传字典,传列表需要添加safe=False
return JsonResponse(li,safe=False)

六、StreamingHttpResponse类

StreamingHttpResponse类被用来从Django响应一个流式对象到浏览器。如果生成的响应太长或者是占用的内存较大,这么做可能更有效率。 例如,它对于生成大型的CSV文件非常有用。
StreamingHttpResponse不是HttpResponse的衍生类(子类),因为它实现了完全不同的应用程序接口。但是,除了几个明显不同的地方,两者几乎完全相同。

七、FileResponse

文件类型响应。通常用于给浏览器返回一个文件附件。
FileResponse是StreamingHttpResponse的衍生类,为二进制文件专门做了优化。
FileResponse需要通过二进制模式打开文件,如下:

>>> from django.http import FileResponse
>>> response = FileResponse(open('myfile.png', 'rb'))

参考文章

http://www.liujiangblog.com/course/django/138

http://www.liujiangblog.com/course/django/140

你可能感兴趣的:(#,Django)