第九章 Django的视图

  • 9.1. View

  • Django使用请求和响应对象来通过系统传递状态。

  • 当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。

  • 然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。

  • 每个视图负责返回一个HttpResponse对象。

9.1.1 views.py

  • 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

  • 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

  • 无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

9.1.2 FBV和CBV

  • FBV:function based view

  • CBV:class based view。api开发

 1. CBV语法

  • 处理请求的逻辑清晰

# cbv示例
from django.views import View
class AddPublisher(View):
  def get(self, request, *args, **kwargs):
    """处理get请求"""
    return response
  def post(self, request, *args, **kwargs):
    """处理post请求"""
    return response 
  def delete(self, request, *args, **kwargs):
    """处理post请求"""
    return response
  • 使用
# urls.py
url(‘^add_publisher/‘, views.AddPublisher.as_view())
  • as_view流程

  1. 项目加载urls.py时,执行类 as_view() —> view函数

  2. 请求到来时,执行view函数

    1. 实例化类—> self

    2. self.request=request

    3. 执行self.dispatch(request, *args, **kwargs)

  3. 执行self.dispatch(request, *args, kwargs)**方法

    1. 判断请求方式是否被允许(不允许: 405)

      • 允许:通过反射获取对应请求方式的方法—> 赋值给handler

        • return handlder(request, *args, **kwargs)

      • 不允许:self.http_method_not_allowed —> handler

        • return handlder(request, *args, **kwargs)

    2. 执行handler(request, *args, **kwargs)

9.2. 视图加装饰器

  • 使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。

9.2.1 视图函数加装饰器

# FBV加装饰器
# 装饰器函数
from time import time
def timer(func):
      def inner(*args, **kwargs):
        start = time()
        ret = func(*args, **kwargs)
        print(time() - start)
        return ret
    return inner
# 给视图函数加装饰器
@timer
def fun():
  pass

9.2.2 给类方法加装饰器

1. 给某个方法加

  • 导入View类、导入method_decorator

  • 类中定义对应请求的方法

  • 使用带参数的装饰器

# CBV加装饰器
from django.utils.decorators import method_decorator
from django.views import View
class AddPublisher(View):
      def get(self, request):
        # 处理get请求
        return response
      # 给post方法加装饰器
      @method_decorator(timer)
      def post(self, request):
            # 处理post请求
            return response 
      def delete(self, request):
            # 处理post请求
            return response

2. 给dispatch加

  • 给dispatch加装饰器,所有方法都会生效

from django.views import method_decorator
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):
      ret = super().dispatch(request, *args, **kwargs)
    return ret

3. 在类上加

  • 加在类上,只对指定的name方法有效

from django.views import method_decorator
@method_decorator(timer, name=‘get‘)
@method_decorator(timer, name=‘post‘)
class AddPublisher(View):
      def get(self, request):
        # 处理get请求
        return response
      def post(self, request):
            # 处理post请求
            return response 
      def delete(self, request):
            # 处理post请求
            return response

4. 在类上加

  • 指定name=‘dispatch‘,所有方法都生效

from django.views import method_decorator
@method_decorator(timer, name=‘dispatch‘)
class AddPublisher(View):
      def get(self, request):
        # 处理get请求
        return response
      def post(self, request):
            # 处理post请求
            return response 
      def delete(self, request):
            # 处理post请求
            return response

Note(2)

  • 不使用导入method_decorator时

  1. method_decorator

    • 是一个函数,其作用:Converts a function decorator into a method decorator

  2. 传入的参数将会发生变化

9.3. reuqest对象

  • django将请求报文中的请求行、头部信息、内容主体封装成 HttpRequest 类中的属性

  • 除了特殊说明的之外,其他均为只读的。

9.3.1 request对象的属性

  • 封装请求中的所有内容

  • 常用的是前5种


属性
含义
1request.path_info/path返回用户访问url,不包括域名
2request.method请求中使用的HTTP方法的字符串表示,全大写表示。
3request.GET包含所有HTTP GET参数的类字典对象,QuerySet
4request.POST包含所有HTTP POST参数的类字典对象QuerySet
5request.bodyhttp请求体byte类型 request.POST的数据就是从body里面提取到的
6request.scheme请求方案,通常为http 或 https
7request.encoding编码方式,为None则则表示使用 DEFAULT_CHARSET 的设置,默认为 ‘utf-8‘)。
8request.FILES上传的文件
9request.META获取请求头,全大写,加HTTP, - 变称_s
10request.userDjango提供的auth模块,获得当前登陆的用户
11request.session 
12request.COOKIES 
  • FILES属性示例
file_name = request.FILES.get(‘file‘).name
f1 = request.FILES.get(‘f1‘)
with open(f1.name, ‘wb‘) as f:
  # 必须使用chunks()方法,否则会报错
  for i in f1.chunks():
    f.write(i)
# 保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
# 但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。

Note(4)

  1. get请求没有请求体

  2. Encoding

    • 这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。

    • 如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它

  3. FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象

  4. 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。

9.3.2 方法

 

方法含义
1request.get_full_path()url路径,不包含ip端口,包含参数
2request.get_host()ip和端口
3request.is_ajax()是否使用ajax
4request.is_secure()http是否时加密的,https
5request.get_signed_cookies()获取加密的cookie
6request.get_raw_url()获取全部url

9.4. response对像

9.4.1. response

  • 与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse

  1. HttpResponse(‘字符串‘)。类 content-type=‘text/html‘

  2. render(request, ‘模版.html‘, {‘key‘: value})。函数

    • content进行字符串替换

    • 返回的是HttpResponse对象

    • render_to_string():进行字符串替换

  3. redirect(‘/重定向的地址/‘)

    • 返回的是HttpResponse对象

  4. JsonResponse

    • 前后端分离通过json传送数据

    • HttpResponse(dic):前端只能看到key值

    • dic序列化后,可以在前端显示

    • content-type=‘text/html‘

9.4.2 HttpResponse使用

  • HttpResponse类位于django.http模块中。

1. 传递字符串

# 导入 HttpResponse 类
from django.http import HttpResponse
response = HttpResponse(‘welcom to our site‘)
response = HttpResponse(‘Text only, please‘, content_type=‘text/plain‘)

2. 设置或删除响应头信息

response = HttpResponse()
response[‘Content-Type‘] = ‘text/html; charset=UTF-8‘
del response[‘Content-Type‘]

3. 属性

  1. HttpResponse.content:响应内容

  2. HttpResponse.charset:响应内容的编码

  3. HttpResponse.status_code:响应的状态码

9.5. JsonResponse对象

  • JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

from django.http.response import JsonResponse
def json_data(request):
  data = [‘name‘:‘henry‘, ‘age‘: 19]
  ret = HttpResponse(data)
  # 自己序列化,并指定类型(不导入模块的情况下使用)
  ret[‘Content-Type‘] = ‘applicatoin/json‘
  return ret
    # 或
  return HttpResponse(data,content-type = ‘applicatoin/json‘)
# 前端获取数据会自动反序列化
# 默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
return JsonResponse([1,2,3],safe=False)

9.6. shortcut functions

9.6.1 render()

1. render的使用

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

from django.shortcuts import render
def index(request):
        return render(request, ‘index.html‘, {‘k1‘:v1})
  • 等价于
from django.http import HttpResponse
from django.template import loader

def index(request):
  # 视图代码
      t = loader.get_template(‘index.html‘)
    d = {‘k1‘:v1}
    return HttpResponse(t.render(d, request))

2. 参数详解

  • request: 用于生成响应的请求对象。

  • template_name:要使用的模板的完整名称,可选的参数

  • context=None:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

  • content_type=None:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为‘text/html‘

  • status=None:响应的状态码。默认为200。

  • using=None: 用于加载模板的模板引擎的名称。

9.6.2 redirect()

1. 参数类型

  • 一个模型:将调用模型的get_absolute_url() 函数

  • 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称

  • 一个绝对的或相对的URL,将原封不动的作为重定向的位置

  • 默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。

2. 示例

def my_view(request):
  ...
  # 永久重定向,为False时为临时重定向
  return redirect(‘/index/‘, permanent=True)
3. 临时重定向和永久重定向
  1. 临时重定向(响应状态码:302)和永久重定向(响应状态码:301)对普通用户来说是没什么区别的,它主要面向的是搜索引擎的机器人。

  2. A页面临时重定向到B页面,那搜索引擎收录的就是A页面。

  3. A页面永久重定向到B页面,那搜索引擎收录的就是B页面。