django-response对象

时间:2022-06-08 06:16:06

HttpResponse 对象则需要 web 开发者自己创建,一般在视图函数中 return 回去。下面我们就来看看 HttpResponse 对象的各种细节

首先,这个对象由 HttpResponse 类创建,这个类位于 django.http 模块中,所以在使用的时候还先从模块中导入这个类。

from django.http import HttpResponse

构造函数

然后,我们需要知道传递什么参数,这个时候先看看其构造函数是怎么样的。

HttpResponse.__init__(content='', content_type=None, status=200, reason=None, charset=None)

content:可以是一个迭代器或字符串。如果是一个迭代器,HttpResponse 将立即处理这个迭代器, 把它的内容转成字符串,并丢弃这个迭代器。如果你需要从迭代器到客户端的数据响应以数据流的形式, 你必须用 StreamingHttpResponse 类代替;如果是一个字符串(迭代器处理后的或手动传入的),那么这个字符串将作为相应报文的主体内容,也就是说如果是一个 http 文档,那么这个文档将会放入响应报文的主体中,最后在浏览器中显示,这也是最为常用的方式之一。

  content_type:用于指定 MIME 类型和编码,例如:“text/html; charset=utf-8”。客户端需要知道主体是什么类型的资源,才能调用相应的插件或内置的程序去处理。如果不传入,也就是为 None 时,将使用 DEFAULT_CONTENT_TYPE 的值来指定 MIME 类型,这个值默认为:'text/html';使用 DEFAULT_CHARSET 的值来指定文件编码,默认为:'utf-8'。

  status:响应状态码,200代表成功,一般不需要改变,除非有特殊要求。

  reason:原因短语,也就是 200 ok 中的 ‘ok’,因为客户端是根据状态码来判断响应是否成功的,所以 reason 的影响几乎为 0 ,只是对人的提醒而已。如果没有指定, 则使用默认响应短语。也就是 200 就对应于 ok,404 就对应于 not found。

  charset:在response中被编码的字符集。如果没有给定(也就是为None),将会从 content_type 中提取,如果提取不成功, 那么 DEFAULT_CHARSET 的设定将被使用。

使用相关的属性去查看这些值:

HttpResponse.content :表示内容的字符串,对应于我们传入的 content 参数的值。

HttpResponse.charset :一个表示编码的字符串,对应于 charset 参数,如果实例化的时候没有给定,将从 content_type 中解析出来,如果解析失败,将使用 DEFAULT_CHARSET 的值。

HttpResponse.status_code :表示响应的状态码。在 1.9 中除非 reason_phrase 属性被显式的设置,否则在构造函数外修改状态码时,也会修改 reason_phrase 属性。也就是说,当我们在创建实例的时候,并没有设置 reason ,原来的状态码是 200 ,当我们在构造器外修改这个属性的时候,如修改成 404,那么 reason_phrase 属性就变成对应的 not found。

HttpResponse.reason_phrase :表示响应的原因短语,对应于 reason 参数。在1.9中 reason_phrase 不再默认为全部大写字母。现在使用 HTTP 标准的默认原因短语。除非显式设置,reason_phrase 由status_code 的值的确定。

HttpResponse.streaming :这个选项总是 False。由于这个属性的存在,使得中间件(middleware)能够区别对待流式 response 和常规 response 。

HttpResponse.closed :如果响应已关闭,则是 True 的。

HttpResponse.__setitem__(header, value)
由给定的首部名称和值设定相应的报文首部。 header 和 value 都应该是字符串类型。

HttpResponse.__delitem__(header)
根据给定的首部名称来删除报文中的首部。如果对应的首部不存在将沉默地(不引发异常)失败。不区分大小写。

HttpResponse.__getitem__(header)
根据首部名称返回其值。不区分大小写。

HttpResponse.has_header(header)
通过检查首部中是否有给定的首部名称(不区分大小写),来返回 True 或 False 。

HttpResponse.setdefault(header, value)
设置一个首部,除非该首部 header 已经存在了。

另外,我们还可以使用类字典的方法来设置首部,例如:

>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']

注意:当调用 del 去删除的首部不存在时,会引发 KeyError 异常。

  但是,当我们设定 Cache-Control 首部和 Vary 首部时,推荐使用 patch_cache_control() 和 patch_vary_headers()方法,可以从 django.utils.cache 中导入它们。因为这两个首部通常有多个值,这些值都要逗号隔开。"patch" 方法可以确保这些值,例如由中间件添加的值不会被改变。而字典形式添加的,同名键的不同值会发生冲突,只有最后一个值有效。

  另外,虽然标准的 HTTP 报文中要求首部的每一行都要使用换行符隔开,但是 django 已经帮我们做了这些,所以我们不用重复的添加换行符了,否则会触发 BadHeaderError 异常。

HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)

  设置一个Cookie。参数与Python 标准库中的 Morsel Cookie 对象相同。
  key:键名,字符串形式。
  value:对应的值,字符串形式。
  max_age:cookie 过期的相对时间,单位是秒。如果为None,则当浏览器关闭的时候过期。如果设置了 max_age 而没有设置 expires,则 expires 将根据 max_age 的值计算出来。
  expires:设置 cookie 过期的绝对时间。应该是一个 UTC "Wdy, DD-Mon-YY HH:MM:SS GMT" 格式的字符串,或者一个 datetime.datetime 对象。如果 expires 是一个datetime 对象,则 max_age 会通过计算得到。
  path:一个字符串,表示客户端回送 cookie 的路径,如果为‘/’,则表示该域名下的所以路径都将回送 cookie,如果是‘/blog/’;则在访问‘/blog/abc’或者‘/blog/def’等,所有包含该前缀的路径时,客户端都会回送 cookie。
  domain:cookie有效的域。例如,其值为‘.scolia.com’时,那么在访问 www.scolia.com 或者 test.scolia.com 之类的时,都会回送 cookie ,当然通常会和 path 配合在一起使用。根据 HTTP 协议的要求,这个值必要要两到三个句点,从而防止出现 ‘.com’、‘.edu’、‘va.us’等形式的域名。当域为高层域时,只要两个句点就可以了,而高层域包括:.com、.edu、.net、.org、.gov、.mil、.int、.biz、.info、.name、 .museum、.coop、.aero、和.pro。其他的域则需要至少三个。
  secure:当其为 True 时,表示只要在 https 连接的情况下才会回送cookie
  httponly:当其为 True 时,JavaScript 等就不能访问对应的cookie了。当然这个标记并不是cookie标准中的,但目前市面上常用的浏览器都支持。灵活使用可以提供数据的安全性。

注意:
  RFC 2109 和RFC 6265 都声明客户端至少应该支持 4096 个字节的Cookie。对于许多浏览器,这也是最大的大小。如果视图存储大于 4096 个字节的 Cookie,Django 不会引发异常,但是浏览器将不能正确设置 Cookie。

HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)

  与 set_cookie() 类似,但是在设置之前将用密钥签名,也就是常说的加盐处理。通常与 HttpRequest.get_signed_cookie() 一起使用。你可以使用可选的 salt 参数来增加密钥强度,但需要记住在调用 HttpRequest.get_signed_cookie() 时,也要把使用的 salt 参数传入,用于解密。

HttpResponse.delete_cookie(key, path='/', domain=None)
  在cookie中删除指定的 key 及其对应的 value。如果 key 不存在则什么也不发生,也就是不会引发异常。
  由于 Cookie 的工作方式,path 和 domain 应该与 set_cookie() 中使用的值相同 —— 否则 Cookie 不会删掉。

HttpResponse.write(content)
  将 content 写到报文的主体中,这使得 HttpResponse 的实例类似于文件对象。
  类似的还有:
  HttpResponse.flush() :将缓存区的内容写入到报文中
  HttpResponse.tell() :移动文件中的操作指针

HttpResponse.getvalue()
  从 HttpResponse.content 中返回其值。这使 HttpResponse 的实例类似于数据流对象。

HttpResponse.writable()
  总是 True,表示其是可写的。这使 HttpResponse 的实例类似于数据流对象。
 
HttpResponse.writelines(lines)
  在内容中写入一行。不添加行分隔符。这使 HttpResponse 的实例类似于数据流对象。

HttpResponse的子类

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

class HttpResponseRedirect
  构造函数的第一个参数是必要的 — 用来重定向的地址。这些能够是完全特定的URL地址(比如,'http://www.yahoo.com/search/'),或者是一个不包含域名的绝对路径地址(例如, '/search/')。关于构造函数的其他参数,可以参见 HttpResponse。注意!这个响应会返回一个302的HTTP状态码。
  url:一个只读属性,表示代表响应将会重定向的URL地址(相当于Location 首部信息)。

class HttpResponsePermanentRedirect
  与 HttpResponseRedirect 一样,但是它会返回一个永久的重定向(HTTP状态码301)而不是一个“found”重定向(状态码302)。

class HttpResponseNotModified
  构造函数不会有任何的参数,并且不应该向这个响应(response)中加入内容(content)。使用这个意味着资源在用户最后一次请求之后,没有修改过(状态码304)。

class HttpResponseBadRequest
  与HttpResponse的行为类似,但是使用了一个400的状态码。表示一个错误的请求。

class HttpResponseNotFound
  与HttpResponse的行为类似,但是使用了一个404的状态码。表示资源没有找到。

class HttpResponseForbidden
  与HttpResponse的行为类似,但是使用了一个403的状态码。表示用户无权访问。

class HttpResponseNotAllowed
  与HttpResponse的行为类似,但是使用了一个405的状态码。表示请求的方法不被允许。 构造函数的第一个参数是必须的:一个允许使用的方法构成的列表(例如,['GET', 'POST'])。也就是说不在列表中的方法就是不被运行的方法。

class HttpResponseGone
  与HttpResponse的行为类似,但是使用了一个410的状态码。表示服务器曾经拥有过此资源。主要是在 web 站点进行维护的时候,通知客户端。

class HttpResponseServerError
  与HttpResponse的行为类似,但是使用了一个500的状态码。表示服务器内部错误。

注意:如果一个自定义的 HttpResponse 的子类实现了 render 方法,那么 django 会将其当作一个 SimpleTemplateResponse。 render 方法必须返回一个有效的响应对象。

JsonResponse

json是目前常用的一种数据格式,有时候我们需要返回一个json格式的数据,而 JsonResponse 提供了一个快捷的方法。
  它是 HttpResponse 的一个子类,用来帮助用户创建JSON 编码的响应。它从父类继承大部分行为,下面看起构造函数:
class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)  
  data:应该传递一个标准的 python 字典给它,它将其转换成 json 格式的数据。
  encoder:默认为 django.core.serializers.json.DjangoJSONEncoder,用于序列化data。关于这个序列化的更多信息参见JSON 序列化。
  safe : 默认为True。如果设置为False,可以传递任何对象进行序列化(否则,只允许dict 实例)。如果safe 为True,而第一个参数传递的不是dict 对象,将抛出一个TypeError。
另外:它的默认 Content-Type 头部设置为application/json。
  json_dumps_params:在1.9版本中新增,可以传递一个python标准的 json 库中,json.dump() 方法处理后的对象给它,用于生成一个响应。
典型的用法如下:

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

序列化非字典对象:

若要序列化非dict 对象,你必须设置safe 参数为False

>>> response = JsonResponse([1, 2, 3], safe=False)

如果不传递safe=False,将抛出一个TypeError

注意:

在EcmaScript 第5版之前,这可能会使JavaScript Array 构造函数崩溃。出于这个原因,Django 默认不允许传递非字典对象给JsonResponse 构造函数。然而,现代的大部分浏览器都已经实现EcmaScript 5,它删除了这种攻击性的数组。所以可以不用关注这个安全预防措施。

修改默认的JSON 编码器:

如果你需要使用不同的JSON 编码器类,你可以传递encoder 参数给构造函数:

>>> response = JsonResponse(data, encoder=MyJSONEncoder)

StreamingHttpResponse

class StreamingHttpResponse
  StreamingHttpResponse类被用来从Django流式化一个响应(response)到浏览器。当生产的响应太长或者占用太多的内存的时候,你可能会使用到它。例如,它对于生成大型CSV文件非常有用。
 
性能方面的考虑:
  django是为了短链接而设计的,也就是说每次响应完毕之后都会断开连接。流式响应将会为整个响应期协同工作进程。这可能导致性能变差。
  总的来说,你需要将代价高的任务移除 请求—响应 的循环,而不是求助于流式响应。

StreamingHttpResponse 不是 HttpResponse 的衍生类(子类),因为它实现了完全不同的应用程序接口(API)。尽管如此,除了以下的几个明显不同的地方,其他几乎完全相同:

应该提供一个迭代器给它,这个迭代器生成出字符串将用来构成内容(content)
    你不能直接访问它的内容(content),除非迭代响应对象本身。这只在响应被返回到客户端的时候发生。
    它没有 content 属性。取而代之的是,它有一个 streaming_content 属性。
    你不能使用类似文件对象的tell()或者 write() 方法。那么做会抛出一个异常

StreamingHttpResponse 应该只在下面的情况下使用:请求是独立的,并且整个内容是不能重复的,在发生给客户端之前。因为其内容(content)是不能访问的,所以很多中间件是无法正常工作的。例如:ETag 和 Content- Length 首部就不能在流式相应中生成。

属性:
StreamingHttpResponse.streaming_content
  一个迭代器,包含内容字符串。

StreamingHttpResponse.status_code
  响应的状态码

StreamingHttpResponse.reason_phrase
  响应的原因短语

StreamingHttpResponse.streaming
  总是True,表示其是一个流式响应。

FileResponse

class FileResponse
  FileResponse是StreamingHttpResponse的衍生类(子类),为二进制文件做了优化。如果 wsgi server 来提供,则使用了wsgi.file_wrapper ,否则将会流式化一个文件为一些小块。
FileResponse 需要通过二进制模式打开文件,如下:

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