django views视图

视图函数简称视图,本质上是一个简单的python函数,它接受web请求并且返回web响应;响应的内容可以是HTML网页、重定向、404错误、XML文档或图像等任何东西,但是,无论视图本身是个什么处理逻辑,最好都返回某种响应

视图函数的代码写在哪都无所谓,只要它在你的python目录下面,但是通常我们约定将视图放置在项目或应用程序目录中的名为views.py的文件中。

1、一个简单的视图

下面是一个返回当前日期和时间作为HTML文档的视图:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

让我们逐行分析一下上面的代码:

首先,从django.http模块导入了HttpResponse类,以及python的datetime库

接着,我们定义了current_datetime视图函数

每个视图函数都接收一个HttpRequest对象作为第一位置参数,一般取名为request,你可以取别的名字,但这不符合潜规则,最好不要那么做

视图函数的名称没有强制规则,但尽量不要和python及django内置的各种名称重名,并且尽量精确地反映出它的功能,比如这里的current_datetime

该视图返回一个HttpResponse对象,其中包含生成的HTML页面。

2、返回错误

在django中返回http错误代码是非常简单的;HttpResponse的许多子类对应着除了200(代表OK)以外的一些常用的http状态码。

为了标识一个错误,可以直接返回那些子类中的一个实例,而不是普通的HttpResponse,想下面这样:

from django.http import HttpResponse, HttpResponseNotFound

def my_view(request):
    # ...
    if foo:
        return HttpResponseNotFound('<h1>Page not found</h1>')
    else:
        return HttpResponse('<h1>Page was found</h1>')

django为404错误提供了一个特化的子类HttpResponseNotFound;由于一些状态码不太常用,所以不是每个状态码都有一个特化的子类。

也可以向HttpResponse的构造器传递HTTP状态码,来创建你想要的任何状态码的返回类,像下面这样:

from django.http import HttpResponse

def my_view(request):
    # ...

    # Return a "created" (201) response code.
    return HttpResponse(status=201)

关键是在返回中提供status=201参数,别的什么303之类的错误都可以参照上面的例子。

3、Http404异常

class django.http.Http404

这是一个django内置的异常类,可以在需要的地方弹出它,django会捕获它,并且带上HTTP404错误码返回你当前APP的标准错误页面或者自定义错误页面,像下面这样:

 from django.http import Http404
from django.shortcuts import render
from polls.models import Poll

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404("Poll does not exist")
    return render(request, 'polls/detail.html', {'poll': p})

为了在django返回404时显示自定义的HTML,可以创建要给名为404.html的HTML模版,并将其放置在模版树的顶层,当DEBUG设置为False时,此模版将被自动使用,当DEBUG为True时,可以向Http404提供消息,它将显示在标准的内置404调试模版中,可以使用这些消息进行调试。

4、Django内置的快捷方法

django在django.shortcuts模块中,为我们提供了很多快捷方便的类和方法,它们都很重要,使用频率很高。

(1)render()

render(request,template_name,context=None,content_type=None,status=None,using=None)

结合一个给定的模版和一个给定的上下文字典,返回一个渲染后的HttpResponse对象。

必须参数:

  • request:视图函数处理的当前请求,封装了请求头的所有数据,其实就是视图参数request
  • template_name:要使用的模版的完整名称或者模版名称的列表,如果是一个列表,将使用其中能够查找到的第一个模版

可选参数:

  • context:添加到模版上下文的一个数据字典,默认是一个空字典,可以将需要提供给模版的数据以字典的格式添加进去,这里有个小技巧,使用python内置的locals()方法,可以方便的将函数作用于内的所有变量一次性添加
  • context_type:用于生成的文档的MIME类型,默认为DEFAULT_CONTENT_TYPE设置的值
  • status:响应的状态码,默认为200
  • using:用于加载模版使用的模版引擎的NAME

示例:

下面的示例将渲染模版myapp/index.html,MIME类型为application/xhtml+xml:

from django.shortcuts import render

def my_view(request):
    # View code here...
    return render(request, 'myapp/index.html', {
        'foo': 'bar',
    }, content_type='application/xhtml+xml')

与下面的示例效果一样:

from django.http import HttpResponse
from django.template import loader

def my_view(request):
    # View code here...
    t = loader.get_template('myapp/index.html')
    c = {'foo': 'bar'}
    return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')

(2)redirect()

redirect(to,permanent=False,args,*kwargs)

根据传递进来的URL参数,返回HttpResponseRedirect

参数to可以是:

  • 一个模型,将调用模型的get_absolute_url()函数,反向解析出目的url
  • 视图名称,可能带有参数:reverse()将用于反向解析url
  • 一个绝对的或相对的URL:将原封不动的作为重定向的目标位置

默认情况下是临时重定向,如果设置permanent=True将永久重定向。

示例:

调用对象的get_absolute_url()方法来重定向URL:

from django.shortcuts import redirect

def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object)

传递视图名,使用reverse()方法反向解析url:

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

重定向到硬编码的URL:

def my_view(request):
    ...
    return redirect('/some/url/')

也适用于完整的URL:

def my_view(request):
    ...
    return redirect('https://example.com/')

所有上述形式都接受permanent参数,如果设置为true将返回永久重定向:

def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object, permanent=True)

(3)get_object_or_404()

get_object_or_404(klass,*args,**kwargs)

这个方法非常有用,常用于查询模型对象,找到则进行下一步处理,如果未找到则给用户返回404页面

在后台,django其实是调用了模型管理器的get()方法,只是返回一个对象,不同的是,如果get()发生异常,会引发Http404异常,从而返回404页面,而不是模型的DoesNotExist异常。

必需参数:

klass:要获取的对象的model类名或者QuerySet等

**kwargs:查询的参数,格式应该可以被get()接受

示例:

从MyModel中使用主键1来获取对象:

from django.shortcuts import get_object_or_404

def my_view(request):
    my_object = get_object_or_404(MyModel, pk=1)

上面的例子同下面一样:

from django.http import Http404

def my_view(request):
    try:
        my_object = MyModel.objects.get(pk=1)
    except MyModel.DoesNotExist:
        raise Http404("No MyModel matches the given query.")

除了传递model名称,还可以传递一个QuerySet实例:

queryset = Book.objects.filter(title__startswith='M')
get_object_or_404(queryset, pk=1)

上面的示例不够简洁,因为它等同于:

get_object_or_404(Book, title__startswith='M', pk=1)

但是如果你的queryset来自其他地方,它就会很有用了

还可以使用manager,如果你自定义了管理器,这将很有用:

get_object_or_404(Book.dahl_objects, title='Matilda')

还可以使用related managers:

author = Author.objects.get(name='Roald Dahl')
get_object_or_404(author.book_set, title='Matilda')

与get()一样,如果找到多个对象将引发一个MultipleObjectsReturned异常。

(4)get_list_or_404()

get_list_or_404(klass,*args,**kwargs)

这其实就是get_object_or_404多值获取版本;在后台,返回一个给定模型管理器上的filer()的结果,并将结果映射为一个列表,如果结果为空则弹出Http404异常

必需参数:

klass:获取该列表的一个model、manager或QuerySet实例

**kwargs:查询的参数,格式应该可以被filter()接受

示例:

下面的示例从mymodel中获取所有发布出来的对象:

from django.shortcuts import get_list_or_404

def my_view(request):
    my_objects = get_list_or_404(MyModel, published=True)

上面的例子同下面一样:

from django.http import Http404

def my_view(request):
    my_objects = list(MyModel.objects.filter(published=True))
    if not my_objects:
        raise Http404("No MyModel matches the given query.")

5、HttpRequest对象

每当一个用户请求发送过来,django将http数据包中的相关内容,打包成为一个HttpRequest对象,并传递给视图函数作为第一个位置参数,也就是reques,视图函数负责返回一个HttpResponse对象

HttpRequest和HttpResponse对象定义在django.http模块中

(1)属性

HttpRequest对象的大部分属性是只读的,除非特别注明

  • HttpRequest.scheme:字符串类型,表示请求的协议种类,如:'http'或‘https’
  • HttpRequest.body:bytes类型,表示原始HTTP请求的正文,它对于处理非HTML形式的数据非常有用,二进制图像、XML等,如果要处理常规的表单数据,应该使用HttpRequest.POST;还可以使用类似读写的方式从HttpRequest中读取数据,参见HttpRequest.read()
  • HttpRequest.path:字符串类型,表示当前请求页面的完整路径,但是不包括协议名或域名;例如:“、music/bands/the_beatles”。这个属性常被用于我们进行某项操作时,如果不通过,返回用户先前浏览的页面
  • HttpRequest.path_info:在某些web服务器配置下,主机名后的URL部分被分成脚本前缀部分和路径信息部分;path_info属性将始终包含路径信息部分,不论使用的web服务器是什么,使用它代替path可以让代码在测试和开发环境中更容易地切换。
  • HttpRequest.method:字符串类型,表示请求使用的HTTP方法,默认为大写,像这样:
if request.method == 'GET':
    do_something()
elif request.method == 'POST':
    do_something_else()

通过这个属性来判断请求的方法,然后根据请求的方法不同,在视图中执行不同的代码。

  • HttpRequest.encoding:字符串类型,表示提交的数据的编码方式(如果为None则表示使用DEFAULT_CHARSET设置)。这个属性是可写的,可以通过修改它来修改表单数据的编码,任何随后的属性访问(如GET或POST)将使用新的编码方式
  • HttpRequest.content_type:表示请求的MIME类型的字符串,从CONTENT_TYPE标头解析
  • HttpRequest.content_params:包含在CONTENT_TYPE标题中的键、值参数字典
  • HttpRequest.GET:一个类似于字典的对象,包含GET请求中的所有参数,详情参考QueryDict文档
  • HttpRequest.POST:一个包含所有POST请求的参数,以及包含表单数据的字典,如果需要访问请求中的原始或非表单数据,可以使用HttpRequest.body属性;POST中不包含上传文件的数据。
  • HttpRequest.COOKIES:包含所有Cookie信息的字典,键和值都为字符串,可以类似字典类型的方式,在cookie中读写数据,但是注意cookie是不安全的因此,不要写敏感重要的信息。
  • HttpRequest.FILES:一个类似于字典的对象,包含所有上传的文件数据,FILES中的每个键为<input type='file' name="" />中的name属性值,FILES中的每个值是一个UploadedFile;要在Django助攻实现文件上传,就要靠这个属性;如果请求方法是POST且请求的<form>中带有enctype="multipart/form-data"属性,那么FILES将包含上传的文件的数据,否则FILES将为一个空的类似于字典的对象,属于被忽略,无用的情形。
  • 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键。

  • HttpRequest.resolver_match:代表一个已解析的URL的ResolverMatch实例
  • HttpRequest.headers:Django 2.2中的新功能,一个不区分大小写的类似dict的对象,它提供对请求中所有HTTP加前缀的标题的访问,每个标题的名称在User-Agent显示是用标题-外壳进行样式化,你可以不区分大小写的访问标头:
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': '127.0.0.1:8000', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch, br', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Cookie': 'sessionid=rff2y86kaa57vpsihwgo5j72v11c4m0i; csrftoken=tPHBVfuGzw4lYSNuaWYEXvJa2oiXlCEZeStm9LSLNfxRKxRY0p6xvYnr0518LN0L'}

(2)可自定义的属性

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

(3)由中间件设置的属性

django的contrib应用中包含的一些中间件会在请求上设置属性:

  • HttpRequest.session:SessionMiddleware中间件,一个可读写的,类似字典的对象,表示当前会话,我们要保存用户状态,回话过程等等,靠的就是这个中间件和这个属性
  • HttpRequest.site:CurrentSiteMiddleware中间件:get_current_site()方法返回的site或RequestSite的实例,代表当前站点是哪个;django是支持多站点的,如果你同时上线了多个站点,就需要为每个站点设置一个站点id
  • 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.

(4)方法

  • HttpRequest.get_host():

根据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()
  • HttpRequest.get_port():使用META中HTTP_X_FORWARDED_PORT和SERVER_PORT的信息返回请求的始发端口
  • HttpRequest.get_full_path():返回包含完整参数列表的path。例如:/music/bands/the_beatles/?print=true
  • HttpRequest.build_absolute_uri(location):返回location的绝对URI形式;如果location没有提供,则使用request.get_full_path()的值;

例如:"https://example.com/music/bands/the_beatles/?print=true"

注:不鼓励在同一站点混合部署HTTP和HTTPS,如果需要将用户重定向到HTTPS,最好使用Web服务器将所有HTTP流量重定向到HTTPS。

  • HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None):从已签名的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('nonexistent-cookie')
...
KeyError: 'nonexistent-cookie'
>>> request.get_signed_cookie('nonexistent-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

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

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

6、QueryDict对象

在HttpRequest对象中,GET和POST属性都是一个django.http.QueryDict的实例。也就是说你可以按本文下面提供的方法操作request.POST和request.GET。
request.POST或request.GET的QueryDict都是不可变,只读的。如果要修改它,需要使用QueryDict.copy()方法,获取它的一个拷贝,然后在这个拷贝上进行修改操作。

(1)方法

QueryDict 实现了Python字典数据类型的所有标准方法,因为它是字典的子类。
不同之处在于下面:

QueryDict.init(query_string=None, mutable=False, encoding=None):QueryDict实例化方法。注意:QueryDict的键值是可以重复的

>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>

如果需要实例化可以修改的对象,添加参数mutable=True

classmethod QueryDict.fromkeys(iterable, value='', mutable=False, encoding=None):

循环可迭代对象中的每个元素作为键值,并赋予同样的值。

>>> QueryDict.fromkeys(['a', 'a', 'b'], value='val')
<QueryDict: {'a': ['val', 'val'], 'b': ['val']}>

QueryDict.__getitem__():返回给定键的值,如果键具有多个值,则返回最后一个值

QueryDict.__setitem__(ke,value):将给定键设置为value,只能在可变的QueryDict上调用

QueryDict.__contains__():判断给定键是否存在

QueryDict.get(ke,default=None):同__getitem__()相同,只是多个了默认值返回

QueryDict.setdefault(key,default=None):它在__setitem__()内部使用

QueryDict.update(other_dict):用新的QueryDict或字典更新当前QueryDict,类似dict.update(),但是追加内容,而不是更新并替换它们,如下:

>>> q = QueryDict('a=1', mutable=True)
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
'2'

QueryDict.items():类似dict.items(),如果有重复项目,返回最近的一个:

>>> q = QueryDict('a=1&a=2&a=3')
>>> list(q.items())
[('a', '3')]

QueryDict.values():类似dict.values(),但是只返回最近的值,如下:

>>> q = QueryDict('a=1&a=2&a=3')
>>> list(q.values())
['3']

QueryDict.copy():使用copy.deepcopy()返回QueryDict对象的副本,此副本是可变的

QueryDict.getlist(key,defautl=None):返回键对应的值的列表,如果该键不存在并且为提供默认值,则返回一个空列表

QueryDict.setlist(key,list_):为list_设置给定的键

QueryDict.appendlist(key,item):将键追加到内部与键相关联的列表中

QueryDict.setdefault(key,default=None):类似dict.setdefault(),为某个键设置默认值

QueryDict.lists():类似items(),只是它将其中的每个键的值作为列表放在一起,如下:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]

QueryDict.pop(key):返回给定键的值的列表,并从QueryDict中移除该值,如键不存在则引发异常

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.pop('a')
['1', '2', '3']

QueryDict.popitem():删除QueryDict任意一个键,并返回二值元组,包含键和键的所有值的列表,在一个空的字典上调用时将引发KeyErro,如下:

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.popitem()
('a', ['1', '2', '3'])

QueryDict.dict():将QueryDict转换为python字典数据类型,并返回该字典,如果出现重复的键,则将所有的值打包成一个列表,改为新字典中键的值

>>> q = QueryDict('a=1&a=3&a=5')
>>> q.dict()
{'a': '5'}

QueryDict.urlencode(safe=Noen):为已编码的格式返回数据字符串:

>>> q = QueryDict('a=2&b=3&b=5')
>>> q.urlencode()
'a=2&b=3&b=5'

使用该safe参数传递不需要编码的字符:

>>> q = QueryDict(mutable=True)
>>> q['next'] = '/a&b/'
>>> q.urlencode(safe='/')
'next=/a%26b/'

7、HttpResponse对象

HttpResponse类定义在django.http模块中

HttpRequest对象由django自动创建,而HttpResponse对象则由程序员手动创建,我们编写的每个视图都要实例化、填充和返回一个HttpResponse对象,也就是函数的return值。

(1)使用方法

传递字符串:

最简单的方式his传递一个字符串作为页面的内容到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 = HttpResponse(b'Bytestrings are also accepted.')

但,如果要增量添加内容,可以将其response用作类文件对象,使用write()方法不断往里增加内容:

>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

传递可迭代对象:

HttpResponse会立即处理迭代器,并把它的内容存成字符串,最后废弃这个迭代器,比如文件在读取后,会立刻调用close()方法,关闭文件

设置头部字段:

可以把HttpResponse对象当作一个字典一样,在其中增加和删除头部字段:

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

注意!与字典不同的是,如果要删除的头部字段如果不存在,del不会抛出KeyError异常。
HTTP的头部字段中不能包含换行。所以如果我们提供的头部字段值包含换行符(CR或者LF),将会抛出BadHeaderError异常

告诉浏览器将响应视为文件附件:

让浏览器以文件附件的形式处理响应,需要声明content_type类型和设置Content-Disposition头信息,给浏览器返回一个微软电子表格:

>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'

(2)属性

HttpResponse.content:响应的内容,bytes类型

HttpResponse.charset:编码的字符集,如果没指定,将会从content_type中解析出来

HttpResponse.status_code:响应的状态码,比如200

HttpResponse.reason_phrase:响应的HTTP原因短语,使用标准原因短语,除非明确设置,否则reason_phrase由status_code的值决定

HttpResponse.streaming:这个属性的值总是False,由于这个属性的存在,使得中间件能够区别对待流式响应和常规响应

HttpResponse.closed:如果响应已关闭,那么这个属性的值为True

(3)方法

HttpResponse.init(content='',content_type=None,status=200,reason=None,charset=None):响应的实例化方法,使用content参数和content_type实例化一个HttpResponse对象;content应该是一个迭代器或者字符串,如果是迭代器,这个迭代器返回的应是字符串,并且这些字符串连接起来形成response的内容,如果不是迭代器或者字符串,那么在其被接收的时候将转换成字符串。

content_type是可选的,用于填充HTTP的content_type头部,如果未指定,默认情况下由DEFAULT_CONTENT_TYPE和DEFAULT_CHARSET设置成:text/html;charset=utf-8

status是响应的状态码,resaon是HTTP响应短语,charset是编码方式

HttpResponse.has_header(header):检查头部中是否有给定的名称(不区分大小写),返回true或false

HttpResponse.__setitem__(header,value):设置标头

HttpResponse.__delitem__(header):删除标头

HttpResponse.__getitem__(header):查看标头

HttpResponse.setdefault(header,value):设置一个头部,除非该头部已经设置过了

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

如果你想阻止客户端的JavaScript访问cookie,可以设置httponly=True

HttpResponse.set_signed_cookie(key,value,salt='',max_age=None,expires=None,path='/',domain=None,secure=None,httponly=True):与set_cookie类似,但是在设置之前将对cookie进行加密签名,通常与HttpResponse.get_signed_cookie()一起使用

HttpResponse.delete_cookie(key,path='/',domain=None):删除cookie中指定的key,由于cookie工作方式,path和domain应该与set_cookie()使用的值相同,否则cookie不会删除

HttpResponse.write(content):将HttpResponse实例看作类似文件的对象,往里添加内容

HttpResponse.flush():清空HttpResponse实例的内容

HttpResponse.tell():将HttpResponse实例看作类似文件的对象,移动位置指针

HttpResponse.getvalue():返回HttpResponse的值,此方法将HttpResponse实例看作是一个类似流的对象

HttpResponse.readable():此方法使HttpResponse实例成为类似流的对象,值始终为False

HttpResponse.seekable():此方法使HttpResponse实例成为类似流的对象,值始终为False

HttpResponse.writable():此方法使HttpResponse实例成为类似流的对象,值始终为True

HttpResponse.writelines(lines):将一个包含行的列表写入响应对象中,不添加分行符

(4)HttpResponse子类

Django包含许多HttpResponse衍生类(子类),用来处理不同类型的HTTP响应,这些子类存在于django.http之中:

class HttpResponseRedirect:用来重定向,第一个参数必须是重定向到的路径,可以是完全限定的URL,或没有域的绝对路径,或者是相对路径;它将返回状态码302

class HttpResponsePermanentRedirect:永久重定向,返回301状态码

class HttpResponseNotModified:未修改页面,返回304状态码

class HttpResponseBadRequest:错误的请求,返回400状态码

class HttpResponseNotFound:页面不存在,返回404状态码

class HttpResponseForbidden:禁止访问,返回403状态码

class HttpResponseNotAllowed:禁止访问,返回405状态码

class HttpResponseGone:过期,返回410状态码

class HttpResponseServerError:服务器错误,返回500状态码

(5)JsonResponse类

classJsonResponse(data,encoder = DjangoJSONEncoder,safe = True,json_dumps_params = None,**kwargs)

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,如果不传递safe=False,将抛出一个TypeError

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

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

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

(6)StreamingHttpResponse类

StreamingHttpResponse类被用来从Django响应一个流式对象到浏览器。如果生成的响应太长或者是占用的内存较大,这么做可能更有效率。 例如,它对于生成大型的CSV文件非常有用。

StreamingHttpResponse不是HttpResponse的衍生类(子类),因为它实现了完全不同的应用程序接口。但是,除了几个明显不同的地方,两者几乎完全相同:

它将被赋予一个迭代器,产生字符串作为内容

除非通过迭代响应对象本身,否则无法访问其内容,只有在将响应返回给客户端时才会发生这种情况

它没有content属性,相反,它有一个streaming_content属性

你不能使用类文件对象tell()或write()方法

(7)FileResponse类

 class FileResponse(open_file,as_attachment = False,filename='',**kwargs)

文件类型响应,通常用于给浏览器返回一个文件附件,FileResponse是StreamingHttpResponse的衍生类,为二进制文件专门做了优化

如果as_attachment=True,则要求浏览器将文件作为下载提供给用户

如果open_file没有名称或名称open_file不合适,请使用filename参数提供自定义文件名

FileResponse接受任何具有二进制内容的类文件对象,如下以二进制模式打开文件:

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

上面的文件将自动关闭,因此不要使用上下文管理器打开它

FileResponse.set_headers方法,在2.1中添加的新功能,它在初始化期间自动调用和设置不同的报头(Content-Length,Content-Type和Content-Disposition),使用哪种报头取决于打开的文件。

-------------------------------------------------------------------------------------------------------------------

 

posted @ 2019-04-28 14:49  Py.qi  阅读(4248)  评论(0编辑  收藏  举报