• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
武纪亨
博客园    首页    新随笔    联系   管理    订阅  订阅
序列化与反序列化及初始drf

内容回顾

# 前后端开发模式
	-混合开发(前后端不分离)--》bbs---》页面渲染是使用模板语法(dtl,jsp-->模板语法,php)-->后端执行-->把页面渲染成纯粹的html,css,js---》直接返回给前端---》浏览器中展示
  	-项目前端用php写的,后端用python写的---》严重错误
    -看到过在html中写php语法--》在后端运行,等同于 dtl
    
    -对后端压力比较大---》每次都要在后端渲染完成
    -后端人员需要写前端东西
    -考你一个问题:写在js中 var name ='{{name}}'
  -前后端分离
  	-页面渲染前端完成---->js语法--》js的dom操作---》jq就是js的一个库
    -前端专门写前端---》html,css,js
    -后端专门写后端--->java,python,go....
    -前端的形式可以是:PC端浏览器,小程序,app---》前后端交互使用json格式
    
  	
    
# API接口
	-前后端交互的媒介
  -咱们自己写的一些后端接口
  -第三方服务对外提供的一些接口----》腾讯发送短信---》使用了第三方的API接口
  -http地址
  
# 后端人员要测试接口---》不能只用浏览器---》浏览器只能发送get请求(除非用ajax)--》postman
	-模拟发送http请求--》指定请求方式,请求地址,请求参数,请求体。。。
  
  -http协议:
    请求协议:请求首行(有哪些东西),请求头(常见请求头),请求体(三种编码格式:urlencoded,formdata,json)
    响应协议:响应首行(状态码),响应头(cookie),响应体(在浏览器中看到的,就是响应体)
    
    
    
# restful规范
	-规范前后端交互api接口
  -10条---》不同公司有公司自己的一些自由规范
  	-https
    -api
    -v1
    -都是用名词,可以复数
    -请求方法决定具体操作:get获取数据,delete删除数据
    -请求地址中带过滤  ?name=xx
    -返回中带状态码  http,自定制状态码
    -返回中带错误信息   msg  err
    -返回数据中带连接
    -返回符合规范:获取所有数据返回列表,单个数据字典,新增返回新增完的,删除返回空文档

内容概要

  • 序列化与反序列化
  • drf介绍和快速使用
  • cbv源码流程分析 (了解)
  • drf之APIView和Request对象分析(了解)

1 序列化和反序列化

api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:

# 序列化: 把我们语言识别的数据转换成指定的格式提供给别人。
					字典,列表,对象------》json/xml/prop,massagepack--->提供给别人(前端或其他服务)

# 反序列化:把别人提供的数据转换/还原成我们需要的格式


我们在django中获取到的数据默认是模型对象(qs对象),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人----》序列化过程

前端传入到后台的数据---》json格式字符串---》后端存到数据库中,需要转成python中的对象---》把json格式字符串转成python对象存到数据库的过程称为反序列化

2 drf介绍和快速使用

# 原生django,不使用任何其他模块,也可以写出符合resful规范的接口---》写起来麻烦一些
# 查询所有图书
	地址:127.0.0.1:8080/books
  路由:path('/books',views.books)
  视图函数中:通过orm查出所有图书(qs)--->序列化(for循环自己拼成列表套字典[{name:西游记,price:99},{name:红楼梦,price:99}])---->JsonResponse返回给前端
  
  
# drf是django的一个app--》帮助咱们快速在django上写符合restful规范的接口

# 安装:
	pip3 install djangorestframework
  注意:django版本 4.x     一般用升级到3.x  或者 2.x
  drf的最新版本最低支持django 3.x以上---》出一个小问题---》装django 2.x---》当你pip3 install的时候,由于低于2.2不支持最新的drf---》把你老版本的django卸载---》给你装上最新版---》原来写的django项目可能有问题,运行不了
  
  2.2一下--->drf降降版本
  3.x---->drf使用最新
  
Python (3.6, 3.7, 3.8, 3.9, 3.10)
Django (2.2, 3.0, 3.1, 3.2, 4.0)

2.1 快速使用

# 针对于一个表,需要写那些接口---》5个--》以后看到的所有接口都是这5个的变形
	-查询所有---》get->http://127.0.0.1:8000/books/
  -查询一个---》get->http://127.0.0.1:8000/books/1/
  -新增一个---》post->http://127.0.0.1:8000/books/ body中带数据
  -修改-----》put,patch--->实际编码中,基本都用put
  	http://127.0.0.1:8000/books/1/ body体中传入修改的数据
  -删除一个---》delete-->http://127.0.0.1:8000/books/1/
  
# 登陆接口---》本质其实是查询一个

# 注册接口----》本质是新增一个

# postman测试,地址要严格,斜杠有和没有是有区别的

视图

from rest_framework.viewsets import ModelViewSet
from .models import Book # 模块导入使用相对导入
# from app01.models import Book # 使用绝对导入
from .serializer import BookSerializer
class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

路由

from rest_framework.routers import SimpleRouter
from app01 import views

router = SimpleRouter()
router.register('books', views.BookView, 'books')
urlpatterns = [
    path('admin/', admin.site.urls),
]
urlpatterns += router.urls

序列化类

from .models import Book
from rest_framework import serializers

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

模型

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=2, max_digits=5)
    author = models.CharField(max_length=32)

3 cbv源码流程分析 (了解)

# cbv路由写法:path('test/', views.TestView.as_view())---》第二个参数是函数内存地址---》as_view()执行完,也是一个内存地址---》闭包函数view的内存地址---》当请求来了,路由匹配成功--》执行view(request),传入当次请求的request对象---->return self.dispatch(request, *args, **kwargs)--->View类中找dispatch---》如果是get请求就会执行视图类中的get方法,如果是post请求,就会执行视图类的post方法




# as_view 类的绑定方法---》View类的方法--》@classonlymethod
# dispatch核心代码---》getattr反射---》从当前对象(视图类的对象)---》如果是get请求--》会拿到get方法---》handler就是get方法---》handler(request)本质就是---》get(request)
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
return handler(request, *args, **kwargs)



# 通过描述符自己写装饰器来装饰类---》完成类似于property,classmethod。。

4 drf之APIView和Request对象分析(了解)

from django.views.generic.base import View # 最真的路径
from django.views.generic import View  # 因为在generic包的init里注册了
from django.views import View       # views包的init里注册了
# APIView的执行流程
路由 path('order/', views.OrderView.as_view())---》第二个参数是函数内存地址---》APIView的as_view的执行结果---》本质还是用了View类的as_view内的view闭包函数,去掉了csrf认证----》当请求来了---》触发view闭包函数执行,并且传入request--->调用了self.dispatch-->self是视图类的对象,从OrderView中找dispatch,但是找不到----》父类APIView中有---》本质执行的dispatch是APIView----》

# APIView的as_view方法
  view = super().as_view(**initkwargs) # 调用APIView的父类(View)的as_view方法
  return csrf_exempt(view) # 去掉csrf_exempt的认证,以后只要继承了APIView后,csrf就无效了,无论中间件是否注释掉

# APIView的dispatch
  def dispatch(self, request, *args, **kwargs):
    	  # request是新的drf提供的request,它是由老的django的request得到的
      	# 通过老request,生成一个新request,drf的Request的对象
        request = self.initialize_request(request, *args, **kwargs)
        # 把新的request,放到了视图类对象中
        self.request = request
        try:
           # 执行了三大认证(认证,权限,频率)
            self.initial(request, *args, **kwargs)
            # self.http_method_names是个列表
            if request.method.lower() in self.http_method_names:
              	# 原来dispatch的核心代码
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            # 原来dispatch写的,但是request已经不是老request了,是新的
            response = handler(request, *args, **kwargs) # 执行视图函数的方法
        except Exception as exc:
          	# 无论在三大认证过程中还是执行视图函数方法过程中,只要抛了异常,都会被捕获到
            # 处理全局异常
            response = self.handle_exception(exc)

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


      
# APIView执行流程---》
  1 包装了新的Request对象,以后视图类中的方法中传入的request对象都是新的
  2 在进入视图函数之前,执行了三大认证
  3 无论三大认证还是视图函数的方法,执行过程中出了异常,都会被处理掉
      
    
    
    
    
    
#  如何包装的新的request
request = self.initialize_request(request, *args, **kwargs)---》APIView的initialize_request---》核心代码
from rest_framework.request import Request
return Request(
            request,  # 老的request
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
新的Request中:self._request = request---》新的request._request是老的request

新的:<class 'rest_framework.request.Request'>
老的:<class 'django.core.handlers.wsgi.WSGIRequest'>

# 三大认证人如何走的
self.initial(request, *args, **kwargs)---》APIView的
核心代码:
   self.perform_authentication(request)  # 认证
   self.check_permissions(request)   #权限
   self.check_throttles(request) # 频率





      
# crsf的局部禁用--》在视图函数上加装饰器---》csrf_exempt装饰器---》装饰器本质就是一个函数
@csrf_exempt       # 装饰器的@ 是一个语法糖(特殊语法)-->把下面的函数当参数传入装饰器中并且把返回结果赋值给函数名:index=csrf_exempt(index)
def index(request)
	pass
跟 csrf_exempt(index) 一毛一样

Request对象分析

# rest_framework.request.Request ---》常用属性和方法
request.data  # 前端post请求传入的数据---》在老的request.POST-->老的只能处理urlencoded和formdata编码格式,json格式不能处理---》无论前端用什么编码post提交的数据,都从data中获取
request.files # 上传的文件对象

以后直接使用新的request.method  request.path 拿到的就是老的request.method...
对象.调用属性或方法会触发 魔法方法 __getattr__
原因在于新的request类重写了__getattr__,以后新的request.method用的时候本质就是request._request.method
  def __getattr__(self, attr):
       try:
            return getattr(self._request, attr)  # 通过反射去老的里面取
        except AttributeError:
            return self.__getattribute__(attr)

          
# 总结:新的request当老的用即可,只是多了个data前端post请求传入的数据,三种编码格式都可以
1 APIView和Request源码部分---》看看---》步骤写一写
2 原来的django的request对象中没有data,写个装饰器,装在视图函数上(中间件),使得request.data-->无论什么编码格式,post提交数据,data都有值
def before(func):
    def inner(request,*args,**kwargs):
        request.data=request.POST
        
        res=func(request,*args,**kwargs)
        return res
    return inner

@before
def test(request):
    print(request.data) #
    return HttpResponse('ok')
posted on 2022-03-30 20:44  Henrywuovo  阅读(82)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3