Django 视图

Django 视图

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

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

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

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

当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。

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

CBV和FBV

基于类的的View,叫CBV(function based view )
基于函数的的View,叫FBV(class based view)

FBV

# 增加出版社
def add_publisher(request):
    # 定义变量
    new_publisher, err_msg = '', ''
    # 判断请求
    if request.method == 'POST':
        new_publisher = request.POST.get('new_publisher').strip()
        # 判断出版社名称是否为空
        if not new_publisher:
            err_msg = '不能为空'
        # 判断出版社是否已存在
        elif models.Publisher.objects.filter(name=new_publisher):
            err_msg = '出版社已存在'
        else:
            models.Publisher.objects.create(name=new_publisher)
            return redirect('/publisher_list/')
    return render(request, 'add_publisher.html', {'new_publisher': new_publisher, 'err_msg': err_msg})

CBV

  1. 定义
# CBV版 add_publisher
# 增加出版社
from django.views import View


class AddPublisher(View):
    def get(self, request):
        return render(request, 'add_publisher.html')

    def post(self, request):
        new_publisher = request.POST.get('new_publisher').strip()
        # 判断出版社名称是否为空
        if not new_publisher:
            err_msg = '不能为空'
        # 判断出版社是否已存在
        elif models.Publisher.objects.filter(name=new_publisher):
            err_msg = '出版社已存在'
        else:
            models.Publisher.objects.create(name=new_publisher)
            return redirect('/publisher_list/')
        return render(request, 'add_publisher.html', {'new_publisher': new_publisher, 'err_msg': err_msg})
  1. 使用
url(r'^add_publisher/', views.AddPublisher.as_view()),
  1. CBV的流程

    1. views.AddPublisher.as_view() 程序加载的时候执行  ——》 view函数
      
    2. 当请求到来的时候执行view函数:

      1. self = AddPublisher()
      2. self.request = request
      3. 执行self.dispatch方法
        1. 判断请求方式是否被允许
          1. 允许时,通过反射获取到AddPublisher中定义的get或者post方法 ——》handler
          2. 不允许时,self.http_method_not_allowed ——》handler
        2. 执行handler 拿到返回结果 Httpresponse对象
  2. 给CBV加装饰器

    from django.utils.decorators import method_decorator
    
    1. 加载某个get/post的方法上:

      @method_decorator(timer)
      def get(self, request):
          pass
      
    2. 加在self.dispatch方法上:

      @method_decorator(timer)
      def dispatch(self, request, *args, **kwargs):
          pass
      
    3. 加在类上:

      @method_decorator(timer, name='post')
      @method_decorator(timer, name='get')
      class AddPublisher(View):
          pass
      
  3. 区别

    1. 不使用method_decorator

    func: <function AddPublisher.dispatch at 0x00000163735176A8>
    args :<app01.views.AddPublisher object at 0x00000163735F7EF0> <WSGIRequest: GET '/add_publisher/'>

    1. 使用method_decorator

    func:<function method_decorator.._dec.._wrapper..bound_func at 0x0000019664B4A378>
    arsgs: <WSGIRequest: GET '/add_publisher/'>

    1. 在普通装饰器中加 def inner(request,*args, **kwargs):,即可起到相同效果

Request对象和Response对象

request对象

当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。

请求相关的常用值

  • path_info 返回用户访问url,不包括域名
  • method 请求中使用的HTTP方法的字符串表示,全大写表示。
  • GET 包含所有HTTP GET参数的类字典对象
  • POST 包含所有HTTP POST参数的类字典对象
  • body 请求体,byte类型 request.POST的数据就是从body里面提取到的
  • path_info 路径信息
  • get_full_path() 路径信息 + 参数
  • get_host() 获取主机
  • META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器
  • FILES 一个类似于字典的对象,包含所有的上传文件信息。

上传文件注意事项:

  1. form表单的enctype = 'multipart/form-data'
  2. request.FILES中获取文件对象
  3. 使用文件对象的chunks()

代码实例

def upload(request):
    '''
    保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
    但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
    :param request:
    :return:
    '''
    if request.method == 'POST':
        # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
        file_name = request.FILES['file_name'].name
        with open(file_name, 'wb') as f:
            # 从上传的文件对象中一点一点读
            for chunk in request.FILES['file_name'].chunks():
                f.write(chunk)
                # 写入本地文件
        return HttpResponse('上传成功!')
    return render(request, 'upload.html')

Response对象

我们写的每个视图都需要实例化,填充和返回一个HttpResponse。
HttpResponse类位于django.http模块中。

HttpResponse

传递字符串

from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")

设置或删除响应头信息

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

属性

  • HttpResponse.content:响应内容
  • HttpResponse.charset:响应内容的编码
  • HttpResponse.status_code:响应的状态码

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

from django.http import JsonResponse
from django.shortcuts import HttpResponse
def json_test(rerquest):
    data = {'name': 'root', 'pwd': '123'}
    ret = JsonResponse(data)  # <JsonResponse status_code=200, "application/json">
    ret2 = HttpResponse(data)  # <HttpResponse status_code=200, "text/html; charset=utf-8">
    ret3 = HttpResponse(data, content_type='application/json')  # <HttpResponse status_code=200, "application/json">
    return ret

Django shortcut functions

render()
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:

  • request: 用于生成响应的请求对象。
  • template_name:要使用的模板的完整名称,可选的参数
  • context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
  • content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'
  • status:响应的状态码。默认为200。
  • useing: 用于加载模板的模板引擎的名称。

redirect()
参数可以是:

  • 一个模型:将调用模型的get_absolute_url() 函数
  • 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
  • 一个绝对的或相对的URL,将原封不动的作为重定向的位置。
    默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。
posted @ 2019-08-03 16:06  写bug的日子  阅读(100)  评论(0编辑  收藏  举报