DRF的序列化【2】

news2025/1/15 12:42:31

【0】前提概要

【1】基于 View + JsonResponse 编写的 5 个接口:

  1. 序列化自定义处理: 你需要自己编写序列化逻辑。
  2. 处理 JSON 格式的 POST 请求数据: 从 request.body 中获取数据,并使用 json.loads() 解析成字典,然后创建相应的对象。
  3. request.POST 和 QueryDict 的区别: request.POST 返回的是 Django 的 QueryDict 对象,与真正的 Python 字典有些差别。您可以通过 request.POST.dict() 方法将其转换为纯字典。
  4. 处理 PUT 请求的数据: PUT 请求的数据不会像 POST 请求那样自动放在 request.PUT 中,您需要自己从 request.body 中提取数据,并进行必要的解析(例如,URL 编码和解码)。
  5. 禁用 CSRF 校验: 注释掉 CSRF 校验,可以在视图函数或者中间件中进行。
	-1 序列化需要自己做
    -2 post提交数据,如果是json格式,在request.POST取不到数据--》request.body
    	dic=json.loads(request.body) # request.body  bytes格式
        Book.objects.create(**dic)
    -3 **request.POST--->QueryDict-->跟真正字典有差距
    	request.POST.get('name')  # {name:[lqz,justin]}
        request.POST['name']
        request.POST.getlist('name')
        看源码:from django.http.request import QueryDict
        request.POST.dict()--->纯字典--**
        
    -4 put请求请求体中的数据--》不会放在request.PUT-->自己从body中转--》url编码和解码
    	django.core.handlers.wsgi.WSGIRequest
    -5 注释掉csrf

【2】基于 APIView + Response 编写的 5 个接口:

  1. 禁用 CSRF 校验: 可以通过在视图函数中使用 @csrf_exempt 装饰器来禁用 CSRF 校验。
  2. 使用装饰器包装视图函数: 您可以编写一个装饰器函数,在其中调用视图函数,并在装饰器中处理一些通用的逻辑,例如异常处理或者权限验证。
	-1 没有csrf校验了---@wrapper
        def index()
		--------------
        wrapper(index)

【3】基于 APIView + Response + 序列化类 编写的 5 个接口:

  1. 编写序列化类: 您需要编写一个继承自 serializers.Serializer 的序列化类,定义需要序列化的字段。
  2. 反序列化校验: 你可以通过字段自定义校验、局部钩子或全局钩子来实现反序列化时的数据校验。
  3. 反序列化保存: 在校验通过后,可以调用序列化器的 save 方法来保存数据,可以根据 instance 的有无来判断是创建新对象还是更新现有对象。
	-1 序列化:写个序列化类,继承Serializer--》写字段--》在视图类中实例化得到对象--》instance,data--》ser.data
    serializer.dat ---> 不是json格式字符串 ---> 字典或者列表 ---> Response ----> json格式字符串
    -2 反序列化校验:(从上往下)
    	-1 字段自己的
        -2 局部钩子  返回值
        -3 全局钩子  返回值
    -3 反序列化保存
    	-1 校验过后 ser.save --->修改,新增
        -2 序列化列中重写 create和update--》都是调用save,但是根据instance有没有决定触发create还是update

【一】全局钩子跟局部钩子

​ 全局钩子(Global Hooks)和局部钩子(Local Hooks)通常是指在软件开发中使用的两种不同类型的钩子机制。

【1】全局钩子

  • 全局钩子是在整个应用程序中生效的钩子,它们会影响应用程序的所有部分。
  • 全局钩子通常用于在应用程序启动或某个特定事件发生时执行某些操作,例如在每个 HTTP 请求处理之前或之后执行某些代码。
  • 在 Web 开发中,全局钩子通常是通过中间件(Middleware)实现的。中间件可以拦截 HTTP 请求和响应,允许开发者在处理请求之前或之后执行自定义代码。
  • 例如,在 Django 中,可以编写中间件来实现全局钩子,这些中间件可以在请求处理的不同阶段执行自定义操作,如身份验证、日志记录等。

全局钩子示例(使用 Django 中间件)

  • 在目录下创建 middleware.py

class RequestLoggingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 在请求处理之前执行的代码
        # 记录请求信息到日志文件
        logger.info(f"Request: {request.method} {request.path}")

        response = self.get_response(request)

        # 在请求处理之后执行的代码
        return response

  • 然后,在 Django 的设置文件中注册这个中间件:

    # settings.py
    
    MIDDLEWARE = [
        # 其他中间件...
        'task_api.middleware.RequestLoggingMiddleware',
    ]
    

【2】局部钩子

  • 局部钩子是针对特定组件或功能的钩子,只在特定的代码段或功能范围内生效。
  • 局部钩子通常用于在特定事件发生时执行某些定制逻辑,例如在模型保存之前或之后执行一些操作。
  • 在软件开发中,局部钩子可以通过回调函数、事件监听器或钩子函数等方式实现。
  • 例如,在 Django 的模型中,可以利用信号(Signals)实现局部钩子,通过监听模型的特定事件(如 pre_savepost_save 等),在事件发生时执行相应的操作。
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from Api01.models import Book


class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()
    publish = serializers.CharField()

    # 局部钩子
    # 1 数据校验第一层,字段自己校验
    # 2 书名不能以sb开头--》局部钩子函数--》给某个字段加限制条件
    def validate_name(self, name):
        # if name.startswith('sb'):
        if 'jni' in name:
            # 不合法,抛异常
            raise ValidationError('书名不能以jni开头')
        else:
            # 合法,返回原来的数据
            return name

小结:

​ 总的来说,全局钩子用于影响整个应用程序的行为,而局部钩子用于在特定场景下执行定制化逻辑。在设计和开发应用程序时,合理地使用全局钩子和局部钩子可以提高代码的灵活性和可维护性。

​ 对单个字段进行校验的方法是局部钩子,而对多个字段进行校验的方法是全局钩子。

【二】APIView源码执行流程

【1】执行流程

​ 当你使用 Django REST Framework 中的 APIView 类时,它提供了一个用于处理 HTTP 请求的类视图,允许你自定义逻辑来响应不同类型的请求(如 GET、POST、PUT、DELETE 等)。让我们来看一下 APIView 的源码执行流程,并结合具体示例来解释:

  1. 初始化视图类:当你定义一个继承自 APIView 的类视图时,首先会创建这个类的实例对象。在这个阶段,会执行类的初始化方法 __init__
  2. 请求分发:当有请求到达时,Django 框架会根据请求的方法(GET、POST、PUT 等)调用对应的方法处理请求。APIView 类中提供了一系列方法来处理不同类型的请求,如 get()post()put()delete() 等。
  3. 请求前处理(dispatch):在调用对应的请求处理方法之前,会先调用 dispatch() 方法进行一些通用的请求预处理操作。这个方法可以被子类重写以添加自定义的请求预处理逻辑。例如,你可以在这个方法中进行身份验证、权限检查等操作。
  4. 请求处理:根据请求的 HTTP 方法,调用对应的请求处理方法,例如 get()post()put()delete() 等。
  5. 请求后处理:在请求处理方法执行完毕后,会进行一些请求后处理操作,比如返回响应数据、设置响应头等。
  6. 返回响应:请求处理方法执行完毕后,会返回一个响应给客户端。
  7. 结束:整个请求处理过程结束。
	-1 请求来:BookView.as_view()(request)-->APIView的as_view--》去除了csrf--》其它跟之前一样(super.super().as_view)--->最终本质就是执行--》self.dispatch-->self 是视图类的对象--》找到APIView的dispatch
    -2 APIView的dispatch
      def dispatch(self, request, *args, **kwargs):
  		# 1 包装新的request--》从此后,request就是新的了
        request = self.initialize_request(request, *args, **kwargs)
        # 2 request新的request放到了self.request中了 【self是视图类的对象】
        self.request = request
		
        try:
            # 3 执行三大认证
            self.initial(request, *args, **kwargs)
            #self.perform_authentication(request)
            #self.check_permissions(request)
            #self.check_throttles(request) 

            # 3 执行跟请求方式同名的方法
            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
			# drf的Response
            response = handler(request, *args, **kwargs)

        except Exception as exc:
            # 4 统一处理一场--》统一返回格式
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

【2】drf 配置文件之查找顺序

在apiView中使用了drf配置文件的默认配置。以下是配置的查找顺序。

'''方式三:查找顺序(一般就用内置的即可)
     1. 视图类  (局部配置)
     2. django settings  (全局配置) 
     3. drf api_settings (内置配置)
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置'''

在django的settings中应该按照如下格式写:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [    # 配置响应
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.TemplateHTMLRenderer',
    ],
    'DEFAULT_PARSER_CLASSES': [  # 配置请求
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
    ],
}
# 注意:所有配置都写在一个REST_FRAMEWORK里面!

【三】drf之请求

【1】APIView之请求相关配置

# 为什么需要进行请求相关配置?
可以定制某些CBV只能只能接收json格式,不能接收其他格式。也就是为了自定义该接口可接受编码格式。

# 默认情况下
前端上传json                  request.data里面是   ---> python字典
前端上传urlencode\formdata    request.data里面是   ---> QueryDict


# 方式一,在继承自APIView及其子类的的视图类中配置(局部配置)
# 总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
    parser_classes = [JSONParser,]
    
# 方式二:在配置文件中配置(影响所有,全局配置)
    -django有套默认配置,每个项目有个配置
    -drf有套默认配置,每个项目也有个配置---》就在django的配置文件中
    REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        # 'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        # 'rest_framework.parsers.MultiPartParser',
    ],
}
       
# 方式三:全局配了1个,某个视图类想要3个,怎么配?
    -只需要在视图类,配置3个即可
    -因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找
    
# 视图类方法中的request
    -data
    -__getattr__
    -query_params

【四】drf之响应

【1】APIView之响应相关配置

# 为什么要在CBV中设置响应相关配置?
因为对于drf的响应,如果使用浏览器和postman访问同一个接口,Response返回的格式是不一样的
	-drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据
    
    
# 方式一:在视图类中写(局部配置)
	-两个响应类---》找---》drf的配置文件中找--》两个类
    -from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
    class BookView(APIView):
    	renderer_classes=[JSONRenderer,]

# 方式二:在项目配置文件中写(全局配置)
    REST_FRAMEWORK = {
      'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}
    
# 方式三:使用顺序(一般就用内置的即可)
     1. renderer_classes
     2. django settings
     3. drf api_settings
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置

【2】Response对象属性

# drf 的Response 源码分析
    -from rest_framework.response import Response
    -视图类的方法返回时,retrun Response ,走它的__init__, init中可以传什么参数
    -Responses最终继承httpresponse.
    
    
# Response init可以传的参数
    def __init__(self, 
                 data=None, 
                 status=None,
                 template_name=None, 
                 headers=None,
                 exception=False, 
                 content_type=None)
    
   -data:之前咱们写的ser.data  可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个 

   -status: http响应的状态码,默认是200,你可以改
        -drf在status包下,把所有http响应状态码都写了一遍,常量
        -from rest_framework.status import HTTP_200_OK
        -Response('dddd',status=status.HTTP_200_OK)
      
   -template_name:了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制

   -headers:响应头,http响应的响应头 示例:header={'xxx':'yyy'}
    
   -content_type :响应编码格式,一般不动
   
# 重点:data,status,headers

# 原生djagno,如何在响应头中加东西?

           '''
           四件套 render,redirect,HttpResponse,JsonResponse
           方法: 产生HttpResponse然后添加属性
           '''
         # 示例:
            obj = HttpResponse('dddd')
            obj['xxc'] = 'yyc'
            return obj
        
         响应头添加属性涉及知识 ---> 跨域 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1646352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue入门到关门之Vue3项目创建

一、vue3介绍 1、为什么要学习vue3? vue3的变化: 首先vue3完全兼容vue2,但是vue3不建议用vue2的写法;其次,vue3拥抱TypeScript,之前vue2使用的JavaScript,ts完全兼容js 最后之前学的vue2 是…

JavaScript 中的 Class 类

🔥 引言 在ECMAScript 2015(ES6)中,class 关键字被引入,为JavaScript带来了一种更接近传统面向对象语言的语法糖。类是创建对象的模板,它们封装了数据(属性)和行为(方法&…

25.哀家要长脑子了---哈希表

1.525. 连续数组 - 力扣(LeetCode) 在我对通义千问的一番折磨下,终于弄清楚一点点了。哈希表存储前缀和数组值 用一个counter来记录nums中0、1数量差值的变化。 哈希表map存储某个特定的counter值首次出现的位置。counter的计算:…

2023年乡镇街道边界数据、行政村边界、省市县区划边界、建筑轮廓边界数据、流域边界数据、降雨量分布、气温分布、道路网分布

数据范围:全国行政区划-行政乡镇街道边界 数据类型:面状数据,全国各省市县【乡镇-边界】乡村界、乡村范围 数据属性:标准12位行政区划编码、乡镇名称、所属地区 分辨率:1:2万--1:5万 数据格式:SHP数据&…

力扣100284. 有效单词(C++)

【题解】 (实际在力扣中运行的代码只需要把下方的check函数放到力扣作答区给的模板中就可以) #include <bits/stdc.h> #include <iostream> #include <vector> #include <string> #include <cctype> #include <cstring> #include <st…

【简单介绍下Debian常用命令】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

tomcat-以服务的方式重启tomcat

背景 双击tomcat的bin目录下面的startup.bat&#xff0c;会留下一个cmd的窗口&#xff0c;很不优雅 使用service服务的方式启动&#xff0c;并且设置为自动启动 找到tomcat的bin目录输入cmd&#xff0c;按Enter&#xff0c;进入命令行界面。执行“service.bat install” 。&…

最近惊爆谷歌裁员

Python团队还没解散完&#xff0c;谷歌又对Flutter、Dart动手了。 什么原因呢&#xff0c;猜测啊。 谷歌裁员Python的具体原因可能是因为公司在进行技术栈的调整和优化。Python作为一种脚本语言&#xff0c;在某些情况下可能无法提供足够的性能或者扩展性&#xff0c;尤其是在…

【小菜鸟之---Ansible基础详解】

文章目录 1 【Ansible简介】1.1简介1.2 Ansible 特点1.3 Ansible的工作机制1.4Ansible任务工作模式 2【安装部署】2.1安装命令2.2 Ansible配置文件2.3主机清单配置2.4 基于ssh免密登录2.5常用命令 3【Ansible常用模块】3.1 ping模块3.2 shell模块3.3 command模块3.4 copy模块3.…

【notes2】并发,IO,内存

文章目录 1.线程/协程/异步&#xff1a;并发对应硬件资源是cpu&#xff0c;线程是操作系统如何利用cpu资源的一种抽象2.并发&#xff1a;cpu&#xff0c;线程2.1 可见性&#xff1a;volatile2.2 原子性&#xff08;读写原子&#xff09;&#xff1a;AtomicInteger/synchronized…

【从零开始学架构 前言】整体的学习路线

本文是《从零开始学架构》的第一篇学习笔记&#xff0c;在工作6年左右的这个时间点需要有一些先行的理论来指导即将面临的复杂实践&#xff0c;以便在真正面临复杂实践的时候能有所参照。 主要从以下几个方面和顺序来进行学习 架构基础&#xff1a;从架构设计的本质、历史背景…

# 怎么关闭 win10 系统中自带的【文件预览】功能?关闭WIN10【文件预览】功能的方法

怎么关闭 win10 系统中自带的【文件预览】功能&#xff1f;关闭WIN10【文件预览】功能的方法 win10 系统中自带的【文件预览】功能&#xff0c;默认是开启状态的&#xff0c;如果需要关闭它&#xff0c;一步搞定。 1、打开电脑文件浏览器&#xff0c;随便进入有文件的一个文件…

【Linux】操作系统

上一篇博客我们从硬件的角度谈了计算机&#xff0c;我们说到了计算机的效率跟操作系统写的好不好有着直接的关系&#xff0c;那么这篇博客我们从软件的角度&#xff0c;就来谈一谈究竟什么是操作系统&#xff0c;为什么要有操作系统&#xff1f; 首先我们来大体的认识一下操作…

php基础知识快速入门

一、PHP基本知识 1、php介绍&#xff1a; php是一种创建动态交互性的强有力的服务器脚本语言&#xff0c;PHP是开源免费的&#xff0c;并且使用广泛。PHP是解释性语言&#xff0c;按顺序从上往下执行&#xff0c;无需编译&#xff0c;直接运行。PHP脚本在服务器上运行。 2、ph…

解决 java: 非法字符: ‘\ufeff‘

【报错解释】&#xff1a; 该错误通常发生在尝试编译Java源代码文件时&#xff0c;文件开头的字符是一个字节顺序标记&#xff08;Byte Order Mark&#xff0c;BOM&#xff09;&#xff0c;即\ufeff。在Java中&#xff0c;\ufeff不是一个合法的字符&#xff0c;因此编译器会报…

【码银送书第十九期】《图算法:行业应用与实践》

作者&#xff1a;嬴图团队 01 前言 在当今工业领域&#xff0c;图思维方式与图数据技术的应用日益广泛&#xff0c;成为图数据探索、挖掘与应用的坚实基础。本文旨在分享嬴图团队在算法实践应用中的宝贵经验与深刻思考&#xff0c;不仅促进业界爱好者之间的交流&#xff0c;…

图卷积神经网络GCN

计算图 通过消息传递的框架构建一个局部邻域的计算图 每个节点分别构建自己的计算图 理论上任意深度&#xff0c;根据六度空间理论&#xff0c;层数一般不会超过六层 基本过程 数学形式 矩阵表示 代码表示 图计算改进 能够听见自己内心的声音 最终形式 如何训…

Flink时间语义 | 大数据技术

⭐简单说两句⭐ ✨ 正在努力的小叮当~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &a…

抖捧Ai实景直播案例-助力景区商家假期销量爆棚!

出门游玩你会提前做攻略吗&#xff1f;是不是早早就规划好了路线、定好了门票车票。这就是属于消费前置的动作。所以在消费前置的情况&#xff0c;各个景区的商家都铆足劲发展线上流量&#xff0c;短视频直播也成为众多商家必做的宣传渠道&#xff0c;特别是五一假期更让不少商…

C++面向对象程序设计 - 继承与派生进一步讨论

C中所谓“继承”就是在一个已存在的类的基础上建立一个新类&#xff0c;从已有的类那里获得已有特性&#xff0c;叫做类的继承。从另一角度说&#xff0c;从已有的类&#xff08;父类&#xff09;产生一个新的子类&#xff0c;称为类的派生。一个派生类只从一个基类派生&#x…