四十三、视图层

2023-11-13

一 视图函数的返回值

# urls.py
path('index/', views.index)
# views.py
def index(request):
    pass

访问index路由,会报这个视图函数返回的不是一个HttpResponse对象,而是一个None。
在这里插入图片描述
言外之意是调用视图函数返回的必须是一个HttpResponse对象。

# 源码

class HttpResponse(HttpResponseBase):
	pass

def render(
    request, template_name, context=None, content_type=None, status=None, using=None
):
    """
    Return an HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)



def redirect(to, *args, permanent=False, **kwargs):
    """
    Return an HttpResponseRedirect to the appropriate URL for the arguments
    passed.
    """
    redirect_class = (
        HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    )
    return redirect_class(resolve_url(to, *args, **kwargs))

二 视图函数返回json格式数据

  • 方式一:使用json模块
# urls.py

path('json/', views.json)
# views.py

def json(request):
    user_dict = {"name": "jasper", "age": 18, "hobby": ["read", "run", "篮球"]}
    import json
    res = json.dumps(user_dict, ensure_ascii=False)
    return HttpResponse(res)

结果:在这里插入图片描述

  • 方式二:使用JsonResponse模块
# views.py

def json(request):
    user_dict = {"name": "jasper", "age": 18, "hobby": ["read", "run", "篮球"]}
    from django.http import JsonResponse
    return JsonResponse(user_dict)

在这里插入图片描述
怎样解决中文乱码问题?

# 源码

class JsonResponse(HttpResponse):

    def __init__(
        self,
        data,
        encoder=DjangoJSONEncoder,
        safe=True,
        json_dumps_params=None,
        **kwargs,
    ):  # 初始化类对象
        if json_dumps_params is None:  # 当json_dumps_params参数不传时 默认转换成空字典
            json_dumps_params = {}
        kwargs.setdefault("content_type", "application/json")
        # 调用json模块序列化 将json_dumps_params里的关键字参数转换成关键字实参传入dumps函数
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)

dumps函数中不保证时ascii码的参数时ensure_ascii=True,只用将这个参数以字典的形式传入即可。

# views.py

def json(request):
    user_dict = {"name": "jasper", "age": 18, "hobby": ["read", "run", "篮球"]}
    from django.http import JsonResponse
    return JsonResponse(user_dict, json_dumps_params={"ensure_ascii": False})

在这里插入图片描述

  • 序列化一个非字典类型的数据时
# views.py

def json(request):
    user_dict = ["唱", "跳", "rap", "篮球"]
    from django.http import JsonResponse
    return JsonResponse(user_dict, json_dumps_params={"ensure_ascii": False})

在这里插入图片描述
报错信息说,不是一个字典类型对象不能被序列化,需要把safe参数设置成False。

# 源码

class JsonResponse(HttpResponse):

    def __init__(
        self,
        data,
        encoder=DjangoJSONEncoder,
        safe=True,
        json_dumps_params=None,
        **kwargs,
    ):
    	# 这就是抛出异常的代码
    	# 当safe为True并且data的类型不是dict 则会抛出异常
        if safe and not isinstance(data, dict):  
            raise TypeError(
                "In order to allow non-dict objects to be serialized set the "
                "safe parameter to False."
            )

查看源码后发现,只需将safe参数改为False即可。

# views.py

def json(request):
    user_dict = ["唱", "跳", "rap", "篮球"]
    from django.http import JsonResponse
    return JsonResponse(user_dict, json_dumps_params={"ensure_ascii": False}, safe=False)

在这里插入图片描述

三 form表单携带文件数据

# urls.py

path('form/', views.form)
# views.py

def form(request):
    if request.method == 'GET':
        return render(request, 'form.html')
    print(request.POST)
    return HttpResponse('ok')
<body>
    <form method="post">
      <div class="form-group">
        <label for="exampleInputEmail1">Email address</label>
        <input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
      </div>
      <div class="form-group">
        <label for="exampleInputPassword1">Password</label>
        <input type="password" class="form-control" name="password" id="exampleInputPassword1" placeholder="Password">
      </div>
      <div class="form-group">
        <label for="exampleInputFile">File input</label>
        <input type="file" id="exampleInputFile" name="file">
        <p class="help-block">Example block-level help text here.</p>
      </div>
      <div class="checkbox">
        <label>
          <input type="checkbox"> Check me out
        </label>
      </div>
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
</body>

在这里插入图片描述
在这里插入图片描述
request.POST拿到的是一个字符串并不是真正的文件对象,如果想拿到真正的数据,必须满足以下条件。

  1. from标签中请求方式必须是post
  2. from标签中必须有属性enctype=“multipart/from-data”
  3. 后端获取文件数据使用request.FILES
# views.py

def form(request):
    if request.method == 'GET':
        return render(request, 'form.html')
    print(request.POST)
    print(request.FILES)
    return HttpResponse('ok')
<form method="post" enctype="multipart/form-data">

在这里插入图片描述
可以看到request.FILES拿到的可以看作是一个字典,使用方法和GET、POST一致。

将JQuery包导入Django中的static文件夹中:

# views.py

def form(request):
    if request.method == 'GET':
        return render(request, 'form.html')
    file_obj = request.FILES.get('file')
    path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static', file_obj.name)
    with open(path, 'a', encoding='utf8') as f:
        for i in file_obj:
            f.write(i.decode())
    return HttpResponse('ok')

在这里插入图片描述

在这里插入图片描述

四 FBV和CBV

4.1 FBV

基于函数的视图,上面写的全是FBV的,这里就不在写了。

4.2 CBV

基于类的视图:

  • 与特定的HTTP方法(GET、POST等)关联的代码组织能通过单独的方法替换条件分支来解决。
  • 面向对象技术可用于将代码分解为可重用组件。

本质上来说,基于类的视图允许使用不同的类实例方法响应不同的HTTP请求,而不是在单个视图函数里使用有条件分支的代码。

因此,在CBV里处理HTTP中的GET和POST的代码应该像下边这么写。

# views.py

from django.shortcuts import HttpResponse, render
from django.views import View


# Create your views here.


class MyView(View):
    def get(self, request):
        return render(request, 'post.html')

    def post(self, request):
        return HttpResponse('post result')
<form action="" method="post">
        <input class="btn btn-default" type="submit" value="Submit">
 </form>
# urls.py

from django.urls import path
from app01.views import MyView

urlpatterns = [
    path('test/', MyView.as_view()),
]

当触发get请求时:
在这里插入图片描述

点击submit触发post请求时:
在这里插入图片描述

4.3 CBV源码分析

因为Django的URL解析器期望发送请求和相关参数来调动函数而不是类,基于类的视图有一个as_view()类方法。

# View类中的as_view方法

class View:

	...

    @classonlymethod
    def as_view(cls, **initkwargs):
    	...
        return view
  1. 当一个URL被匹配时,会调用我们自己写的类MyView中的as_view方法,但是MyView中没有此方法,但是MyView继承了View类,其实就是执行了View类中的as_view,并返回一个view函数。
# View类中的view函数

   def view(request, *args, **kwargs):
       self = cls(**initkwargs)
       self.setup(request, *args, **kwargs)
       if not hasattr(self, "request"):
           raise AttributeError(
               "%s instance has no 'request' attribute. Did you override "
               "setup() and forget to call super()?" % cls.__name__
           )
       return self.dispatch(request, *args, **kwargs)
  1. 执行view函数,先实例化一个MyView的对象self,再用这个对象调用setup方法(对象再找一个方法,先从对象本身找,再找产生对象的类,没有再找类的父类),这里的setup是View中的。
# View类中的setup方法

def setup(self, request, *args, **kwargs):
     """Initialize attributes shared by all view methods."""
     if hasattr(self, "get") and not hasattr(self, "head"):
         self.head = self.get
     self.request = request
     self.args = args
     self.kwargs = kwargs
  1. 运行setup初始MyView产生的对象,然后调用dispatch方法。
# View类中的dispatch方法


http_method_names = [
        "get",
        "post",
        "put",
        "patch",
        "delete",
        "head",
        "options",
        "trace",
    ]

 def dispatch(self, request, *args, **kwargs):
     # Try to dispatch to the right method; if a method doesn't exist,
     # defer to the error handler. Also defer to the error handler if the
     # request method isn't on the approved list.
     if request.method.lower() in self.http_method_names:
         handler = getattr(
             self, request.method.lower(), self.http_method_not_allowed
         )
     else:
         handler = self.http_method_not_allowed
     return handler(request, *args, **kwargs)
  1. 判断请求方式是不是在 http_method_names 中,如果在,就获取对象的该属性,因为MyView中定义了get方法和post方法,所以对象获取的就是自己本身的,执行并返回。如果不存在就会引发HttpResponseNotAllowed。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

四十三、视图层 的相关文章

随机推荐

  • 记一次python3 pip 报错Retrying

    错误信息如下 Retrying Retry total 4 connect None read None redirect None status None after connection broken by SSLError Can t
  • Nginx超详细入门教程

    目录 一 nginx配置文件介绍 二 nginx的核心功能 1 反向代理 lt 1 gt 正向代理 lt 2 gt 反向代理 lt 3 gt 准备工作 2 负载均衡 3 负载均衡策略 4 动静分离 三 Nginx的高可用性 1 准备两台虚拟
  • Qt控件使用方法技巧合集

    Qt控件使用方法技巧合集 本篇博客代码示例包含C 版本和Python版本 不管是哪个版本 Qt的API都是一样的 使用方式大同小异 文章目录 Qt控件使用方法技巧合集 1 QTextEdit设置背景色和文本颜色 2 QMessageBox的
  • GBK转成utf-8,java实现及讲解,androidstudio学习

    好吧 看来问的人和回答的人都不一定清楚什么是 编码和编码格式 以及如何理解 java中字符串的编码 首先明确几点 unicode是一种 编码 所谓编码就是一个编号 数字 到字符的一种映射关系 就仅仅是一种一对一的映射而已 可以理解成一个很大
  • 连接SqlServer数据库报错version TLS10 is not accepted by client preferences [TLS12,TLS13]

    报错内容 我的报错信息如下 其他类似的可能也好使 你们可以试试 The server selected protocol version TLS10 is not accepted by client preferences TLS12 T
  • 程序员进阶攻略-笔记-021~030

    信息 过载与有效 忙碌 充实而疲倦 的虚幻假象 在这个信息过载的洪流中 需要的就是在这股洪流中筛选信息并建立自己中流砥柱般的 知识磐石 心智 这两个字合在一起是一个意思 分开为 心 和 智 两个字又可以分别解释为 心 是你对需要的选择 从心
  • 八款国产操作系统

    点击上方蓝字 快速关注 目前世界上存在的那些操作系统 Windows MAC OS X MVX DOS VSE UNIX Linux等 很少见到国产操作系统的影子 你知道国产操作系统有那些吗 虽然国内的操作系统我们可能用不上 但我们有足够的
  • sd卡详细资料

    1 简介 SD卡是基于flash的存储卡 SD卡和MMC卡的区别在于初始化过程不同 SD卡的通信协议包括SD总线和SPI两类 SD卡使用卡内智能控制模块进行FLASH操作控制 包括协议 安全算法 数据存取 ECC算法 缺陷处理和分析 电源管
  • Nginx hls流媒体服务器实现直播

    通过Nginx模块nginx rtmp module实现hls流媒体服务器并用OBS进行推流 一 直播协议简介 首先 在搭建服务之前先了解下目前主流的几个直播协议 1 RTMP 实时消息传输协议 Real Time Messaging Pr
  • ERROR:root:Internal Python error in the inspect module.

    Google Colab运行终端命令报错 python xxxxx ERROR root Internal Python error in the inspect module Below is the traceback from thi
  • 维修汽车服务器,修车别被坑,老司机2分钟告诉你,修理厂和4S店之间不为人知的秘密!...

    在修车行业的新闻太多了 也有报道过一辆车坏了一颗螺丝修了几千上万块的新闻并不少见 对于修车多数人的第一反应就是 修车行业太坑了 尤其是私人修理厂 品牌修理店和4S店还稍微好点 但是事实真的是这样吗 首先让我们先了解一下现在的修理行业 现在开
  • 空间战场态势感知系统

    兵工科技 杂志就数字冰雹的 空间战场态势感知指挥可视化系统 对市场总监丁冬先生进行了专访报道 现代战争强调C4ISR技术 指挥中心在千里万里之外 要通过信息化技术对整个海 陆 空 天 电磁战场进行全面的了解 掌握和指挥控制 那么传统指挥部里
  • css在高度为百分比时候的文字垂直居中方法

    对于高度单位是px的div 想让文字垂直居中很简单 line height height就可以了 但是对于高度为百分比的div 如何让文字垂直居中呢 方法一 给需要垂直居中的文字增加一个父元素 给父元素设置 display table 给需
  • Unity3D 万向锁问题

    Unity3D 万向锁问题 1 问题 描述 在 unity3D中 对欧拉角的旋转顺序为Y X Z 那么我们可以通过一个Cube来直观看到这种现象 创建一个Cube 我们只要按照 Y X Z顺序 操作Cubu的Transform属性面板的欧拉
  • 启动gazebo时,[Err] [REST.cc:205] Error in REST request

    启动gazebo时 Err REST cc 205 Error in REST request 1 gazebo在安装ROS的时候就已经安装了 使用以下命令可检查是否安装成功 roslaunch gazebo ros empty world
  • 伸缩自如的ElasticSearch——文档CRUD操作

    文章目录 文档 文档元数据 index type id 取文档 更新文档 创建文档 删除文档 处理冲突 文档 在大多数应用中 多数实体或对象可以被序列化为包含键值对的 JSON 对象 一个 键 可以是一个字段或字段的名称 一个 值 可以是一
  • 移动端测试知识归纳版

    移动端测试 传统手机测试 移动端设备测试 是指测试手机本身 如抗压 抗摔 抗疲劳 抗低温高温等 也包括手机本身的功能 性能等测试 手机应用软件测试 移动端软件测试 手机应用软件是基于手机操作系统之上开发出来的软件 做这样的测试 就称为手机应
  • 如何解决win10 下的Linux子系统WSL忘记用户密码{官网解决方案}

    在使用WSL时 经常需要输入你创建用户名时对应的密码 但是如果忘记了也不要着急 官网提供了解决方法 1 win R 输入cmd后回车确认 进入你得终端 2 在这里输入 wsl u root 后回车 进入你的根目录 可以复制后在终端点击鼠标右
  • spacemacs操作卡顿的解决方法

    打开命令监控寻找卡顿来源 通过minor mode寻找卡顿来源 如何删除插件 删除emacs lisp 终极大法 spacemacs因为功能丰富 对工程操作带来了极大方便 但是因为插件的原因 偶尔会出现卡顿问题 打开命令监控 寻找卡顿来源
  • 四十三、视图层

    视图层 一 视图函数的返回值 二 视图函数返回json格式数据 三 form表单携带文件数据 四 FBV和CBV 4 1 FBV 4 2 CBV 4 3 CBV源码分析 一 视图函数的返回值 urls py path index views