drf2-apiView源码-基本使用-request类源码分析-序列化组件-基本使用-反序列化

  • apiView基本使用
  • apiview源码分析
  • request类源码分析
  • 序列化组件介绍
  • 序列化组件基本使用(查询所有,查询单个)
  • 反序列化(新增,修改)

ApiView基本使用

drf是一个第三方的app,只能再django中使用

ApiView,安装了drf,导入一个视图类APIView,所有后期要使用drf写视图类,
都是继承APIView及其子类

1使用View + jsonRespons写接口

models模型层

from django.db import models

# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)

视图层

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import  View
from .models import Book

#继承一个django的view
class BookView(View):
    def get(self,request):
        book_list = Book.objects.all()
        res_list=[]
        for book in book_list:
            res_list.append({'name':book.name,'price':book.price,'publish':book.publish})
        #booklist 是queryset对象,不能直接序列化,只能通过for循环列表套字典
        return JsonResponse(res_list,safe=False, json_dumps_params={'ensure_ascii':False})#只能序列化字典,列表

路由层

from django.contrib import admin
from django.urls import path
from app01.views import BookView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', BookView.as_view()),
]

image

2.使用apiView+Response获取所有图书接口

drf很规范,封装了,请求类,响应类,路由类,视图类,比较号召

比如响应方法,直接在响应类中。

视图层 views.py 。models.py,urls.py无需变动

from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response

class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res_list)

settings配置 不配置会报一下错误【如果这里使用postman工具则不会报错】

Type Error

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rest_framework'         #注册drf这个app,如果不注册,浏览器访问报错。,如果注册此app,那么展示界面能访问到好看的界面,不仅仅是json格式的
]

image

image

APIView源码分析之执行流程

视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程

#一旦继承了APi View入口
-路由配置跟之前继承view是一样的-->找视图类的as_view--> [APIView的as_view]
class APIView(View):
	......
	.....
    @classmethod
    def as_view(cls, **initkwargs):      
        
  			....
  			.....
        view = super().as_view(**initkwargs)  #又调用了父类(View)的as_view
        view.cls = cls
        view.initkwargs = initkwargs
	# Note: session based authentication is explicitly CSRF validated, 
# all other authentication is CSRF exempt.
#注意:基于会话的认证是显式的CSRF验证,

#所有其他身份验证都是CSRF豁免的。

        return csrf_exempt(view)

跳过了csrf认证,请求来了,路由匹配成功会执行View类的as_view类方法内的闭包函数(但是没了csrf认证)
真正的执行,执行self.dispatch --->ApiView的dispach[重点]

ef dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs
        #参数的request是原来django原生的request
        #下面的request,变成了drf提供的request类的对象-->return Request(...)
       
        request = self.initialize_request(request, *args, **kwargs)
    #self 是视图类的对象,视图类对象.request=request 新的request   
    self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            执行了认证,频率,权限【不读】
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            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

            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

总结

1.只要继承APIView都没有csrf的认证了
2.以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
3.执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4.在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

Request类源码分析

#1.视图类中,使用的request对象,已经变成了request类的对象了

原生django的request是这个类的对象: django.core.handlers.wsgi.WSGIRequest
drf 的request是这类的对象: rest_framework.request.Request

#2request已经不是原来的request了,还能像原来的request一样使用吗?

print(request.method)  #get
print(request.path)       #/books/
print(request.GET)        #原来的get请求提交的参数
print(request.POST)      #原来post请求提交的参数

#3.request源码分析 rest_framework.request.Request

魔法方法:所谓的魔法方法就是类中定义的双下方法,之所以叫魔法方法的原因是达到某个条件,才会触发魔法方法

-类中有个魔法方法:__getattr__ (触发条件 :对象.属性   属性不存在会触发它的执行  )

def  __getattr__(self,attr):  如果取的属性不存在会去原生django的request对象取出来

try:
     #反射:根据字符串获取属性或者方法,self._request是原来的request
     return getattr(self.__request,attr)
  except AttributeError:
  	return self.__getattribute__(attr)
  
  以后i用的所有属性或方法,直接用就可以了---> (通过反射去原来的request中取的)
  
  新的request内部有个老的request,就是request._request
  
  data  是个方法,被property装饰了,变成了数据属性
 
		body体中提交的数据,都从这里取(request.POST)
		  urlencoded,form-data:提交的数据在requst.POST中
  json格式提交的数据,不在requests.POST中,它在request.body中
  	现在无论那种格式,都是从request.data中取
  
  query_params: get 请求提交的参数,等同于request._request.GET 或 request.GET
  其他: 取文件也是从request.FILE中取,跟之前一样

--------------------------------------------------------------------------------------

   验证: 原生requests.POST 只有urlencodedform-data 格式提交的数据,json格式提交的数据在body中自己处理
   但是drf的request中有个data,data中可以取到任意编码提交的数据
   
   request.data 有时候(urlencoded,form-data)QueryDict 有时候json是字典
--------------------------魔法方法----------------------------------------------------------
__ init__   实例化对象的时候自动触发
__ str__   对象被执行打印操作的时候会自动触发,该方法必须返回一个字符串,返回什么字符串打印对象后就展示什么字符串
__ call__  对象加括号调用,自动触发该方法
__ getattr__ 当对象获取一个不存在的属性名,自动给触发,该方法返回什么,对象获取不存在的属性名就会得到什么 
__ set__  对象操作属性值的时候触发,对象.属性名 = 属性值 
__ del__ 对象在被删除(主动,被动) 的时候自动触发
__ getattribute__  对象获取属性的时候,会自动触发,无论这个属性存不存在
__ enter__  对象被with语法执行的时候自动触发,该方法返回什么,as关键字后面的变量就得到什么
__ exit__     对象被with语法执行并运行完with子代码之后,自动触发 

3.序列化组件介绍

3.1什么是序列化?

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

 序列化:把我们识别的数据转换成指定的格式提供给别人

	例如:我们在django中获取到的模型数据默认是模型对象,但是模型对象无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人
反序列化:把别人提供或者提交的数据转换成我们需要的格式,存入数据库
	例如:前端js提供过来的json数据,对py而言就是字符串,我们要进行反序列化换成模型对象,才能保存到数据库中

序列化组件是什么?【重要理解】

drf提供的一个类,我们继承它,写自己的类

序列化的作用?

用来序列化QuerySet或者单个对象

# 获取所有图书接口----》qs,单个book对象转成json格式字符串,给前端---》序列化
	-使用for循环,列表套字典拼接的

drf提供了一种可以快速实现序列化的类:序列化类

4.序列化组件基本使用(查询所有,查询单个)

4.1 定义一个序列化类

新建一个serializer python文件

#写序列化类,给ibook进行序列化
from  rest_framework import serializers

class BookSerializer(serializers.Serializer):
#要序列化的字段,有很多字段类,字段类有很多字段属性
name = seralizers.CharFiled()  字段类
price = serializers.CharFiled()
publish = serializers.CharFiled()

4.2使用序列化类,序列化多条数据

视图类

class BookView(APIView):
	def get(self,request):
	book_list = Book.objects.all()
	#instanace表示序列化的数据,many=True表示序列化多条,(instance是queryset对象,一定要传many=true)
	sr = BookSerializer(instance=book_list,many=True)
	return Response(ser.data)

路由层urls.py不变动,models.py不变动

访问展示效果

image

image

4.3 使用序列化类,序列化单条数据

class BookDetailView(APIView):
    def get(self,request,pk)
    book =Book.objects.filter(pk=pk).first()
    ser = BookSerializer(instance=book)
    return Response(ser.data)

5.反序列化(新增,修改)

新增-修改-->前端传入的数据,要校验--》序列化类有数据校验功能

5.1新增

视图类、

class BookView(APIView) #APIView继承自django的view
	def post(self,request):
	#前端传递数据,从request.data取出来
	ser = BookSerializer(data=request.data)
	if ser.is_valid(): #表示校验前端传入的数据,没有写校验规则,现在等于没校验
		ser.save() #再写东西,这里会报错,调用save会触发BookSerializer的save方法,判断了,如果instance有值执行uodate,没有值执行create
		return Response(ser.data)
	else:
    	  return Response(ser.errors)

序列化类、

class BookSerializer(serializers.Serializer):
#要序列化的字段,有很多字段类,字段类有很多字段属性
	name = serializers.CharFiled()    #字段类
	price = serializers.CharFiled()
	publish = serializers.CharFiled()
	
	
#重写create 方法
def create(self,validated_data)
	res = Book.objects.create(**validated_data)
	return res

image

image

5.2修改

class BookDetailView(APIView):
	def put(self,request,pk):
		book = Book.objects.filter(pk=pk).first()
		#前端传递数据,从request.data取出来
		ser = BookSerializer(instance=book,data=request.data)
	if ser.is_valid():   表示校验前端传入的数据,没有写校验规则,现在等于没校验
		ser.save()  #再写东西,这里会报错,调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,
	没有值执行create
		return Response(ser.data)
	else:
		return Response(ser.errors)

序列化类

class BookSerializer(serializers.Serializer):
	#要序列化的字段,有很多字段类,字段类有很多字段属性
	name = serializers.CharFiled()    #字段类
	price = serializers.CharFiled()
	publish =serializers.CharFiled()

#重写uodate
def update(self,instance,validated_data)
#instance 要修改的对象
#validated_data 校验过后的数据
instance.name = validated_data.get('name'
)
posted @ 2022-09-26 22:01  名字长的像一只老山羊  阅读(30)  评论(0编辑  收藏  举报