叶觉的Django之旅【10-request与类视图】

request 简述

  • 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象。
  • 在django中,视图函数定义的第一个参数总是 request ,如 def request_get_post(request),该参数request简称为请求,是来自HttpRequest对象在django.http模块中定义的HttpRequest对象的API。
  • request 属性
属性 简介 类型
request.body 原始请求主体内容 bytes
request.path 不包含域名的完整访问路径 str
request.method HTTP访问的方法,其中字母必定全是大写。常见有 GET、POST str
request.encoding 提交的数据的编码格式 str
request.content_type 从 header 中解析出的文件类型 str
request.content_params 包含在 header 中的参数 dict
request.COOKIES 包含所有cookies的字典 dict
request.FILES 包含上传的文件 MultiValueDict
request.GET GET请求的参数 QueryDict
request.POST 获取POST方式提交的数据 QueryDict
  • request 方法
方法 简介
request.get_full_path() 返回完整访问路径,包含路径中携带的参数
request.is_secure 判断是否为 https 请求
request.is_ajax() 判断是否为 ajax 请求
  • 更多介绍可以查看官方文档 https://docs.djangoproject.com/zh-hans/2.1/ref/request-response/

request 的 GET 和 POST

  • QueryDict,在一个HttpRequest对象中,GET和POST属性都是django.http.QueryDict的实例,这些实例的类字典类型是为了解决诸如 使用一键多值传输的元素定制的获取值的办法。
  • 使用一个打钩选值的前端模板来测试
<form action="" method="post"> {% csrf_token %}
    <input type="checkbox" name="test" value="测试1"> 测试1
    <input type="checkbox" name="test" value="测试2"> 测试2
    <input type="checkbox" name="test" value="测试3"> 测试3
    <input type="submit">
</form>
  • GET 与 POST 的判断与变更页面的示例
    • 使用request属性中提到的method来判断
    • 当使用GET请求时,返回页面
    • 当使用POST请求时,返回一个POST成功提示
def request_get_post(request):
    if request.method == 'GET':
        return render(request, 'request/request.html')
    if request.method == 'POST':
        return HttpResponse('访问成功')
  • 从页面取值
    QueryDict有两个取值的方法 get() 和 getlist();get() 通过键来获取值,只能获取键的一个值,如果键有多个值,则取到最后一个;getlist() 通过键来获取值,可以获取键的所有值并以列表的形式返回。修改 request_get_psot() 代码,print 打印出 GET 和 POST 取到的值。
    • GET 取值
      • request.GET.get()
      • request.GET.getlist()
    • POST 取值
      • request.POST.get()
      • request.POST.getlist()
def request_get_post(request):
    if request.method == 'GET':
        value = request.GET.get('value')
        values = request.GET.getlist('value')
        print(value)
        print(values)
        return render(request, 'request/request.html')
    elif request.method == 'POST':
        value = request.POST.get('test')	# test 是上面模板checkbox的name
        values = request.POST.getlist('test')
        print(value)
        print(values)
        return HttpResponse('访问成功')
  • GET访问的方法与取到的值
http://172.16.8.128:8000/request/req/?value=abc&value=ova
ova				# get取到的值
['abc', 'ova']	# getlist取到的值
  • POST访问的方法与取到的值
    在这里插入图片描述
测试2				# get取到的值
['测试1', '测试2']	# getlist取到的值

类视图

在这之前,用的视图均由函数创建,称为函数视图,函数视图十分便捷,且易于理解。但是在增加了对GET和POST的不同响应后,代码便不那么易读且复用性不高。为了应对各种各样的请求方法,引入类视图来解决。

  • 类视图来自于 django.views.generic.base.View,所有的其他基于类的视图都从该基类继承,但严格来说,该类并不是一个通用视图,因此可以从 django.views 来导入。
  • 改写上部分代码示例:
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View

class RequestGP(View):

    def get(self, request):
        value = request.GET.get('value')
        values = request.GET.getlist('value')
        print(value)
        print(values)
        return render(request, 'request/request.html')

    def post(self, request):
        value = request.POST.get('test')
        values = request.POST.getlist('test')
        print(value)
        print(values)
        return HttpResponse('访问成功')
  • url 映射方法 as_view()
    类视图不能使用视图函数的映射方法,而应该使用继承于 View 的 as_view(),配置如下
path('req/', RequestGP.as_view())
  • 支持的请求方法
['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

文件上传 InMemoryUploadedFile

  • 从 request.FILES 中可以取得上传的文件
  • 上传的文件为 django.core.files.uploadedfile.InMemoryUploadedFile 类型,以下称"UploadFile"。
  • UploadFile 中含有以下属性和方法,这里主要用到 name 属性和 chunks() 方法
    [‘charset’, ‘chunks’, ‘close’, ‘closed’, ‘content_type’, ‘content_type_extra’, ‘encoding’, ‘field_name’, ‘file’, ‘fileno’, ‘flush’, ‘isatty’, ‘multiple_chunks’, ‘name’, ‘newlines’, ‘open’, ‘read’, ‘readable’, ‘readinto’, ‘readline’, ‘readlines’, ‘seek’, ‘seekable’, ‘size’, ‘tell’, ‘truncate’, ‘writable’, ‘write’, ‘writelines’]
  • UploadFile.name:文件名
  • UploadFile.chunks() :以块为单位进行分片读取

文件上传示例

  1. 创建文件存储目录 media
  2. 在 settings.py 中设置存储路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
  1. 创建用于上传的 form 表单
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="upload">
    <input type="submit">
</form>
  1. 创建类视图
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from mydjango.settings import MEDIA_ROOT
import os
import uuid


class Upload(View):

    def get(self, request):
        return render(request, 'request/upload.html')

    def post(self, request):
        file = request.FILES.get('upload')
        path_name = self.named(file.name)
        
        with open('{}'.format(path_name), 'wb') as f:
            for chunk in file.chunks():
                f.write(chunk)
        return HttpResponse('上传完成')

    def named(self, filename):
        """
        输入一个原文件名
        生成包含文件存储路径的文件名
        :return: a string
        """
        ext = os.path.splitext(filename)[1]
        return os.path.join(MEDIA_ROOT, str(uuid.uuid4()) + ext)
  1. 配置路由映射
path('upload/', Upload.as_view(), name='upload')

END

参考文献

原标题及链接 作者
Request and response objects docs.djangoproject.com
Django Request对象3.3 Lansonli
发布了24 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_39177678/article/details/103714188