APIView与序列化组件使用

1.APIView基本使用

drf:是一个第三方app,只能在django上使用
安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类
获取所有图书接口

1.1使用View+JsonResponse写

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

1.2使用APICView+drf的Response写(不要忘了注册rest_framework这个app)

from rest_framework.view import APIView
from rest_framework.response import Response
from rest_framework.request import Request

class Bookview(APIView): #APIView继承自django的view
	def get(self,request):
		print(request._request)
		print(type(request._request))
		book_list=Book.objects.all()
		#book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
		res_list=[]
		for book in book_list:
			res_list.append({'name':book,'price':book.price,'publish':book.publish})
		return Response(res_list)

2.APIView源码分析

# 视图类继承APIView后,执行流程就发生了变化,这个变化就是整个drf的执行流程
# 一旦继承了APIView入口
	-路由配置跟之前继承view是一样的--->找视图类的as_view--->[APIView的as_view]
		@classmethod
		def as_view(cls,**initkwargs):
			view = super().as_view(**initkwargs)
			'''
			#从此以后,所有的请求都没有csrf的校验了
			#在函数上加装饰器
			@csrf_exempt
			def index(request):
				pass
			本质上等同于 index = csrf_exempt(index)
			'''
			return csrf_exempt(view)
	-请求来了,路由匹配成功会执行 view类的as_view类方法内的view闭包函数(但是没有了csrf认证)
	-真正的执行,执行self.dispatch--->APIView的dispatch[这是重点]
	def dispatch(self,request,*args,**kwargs):
		#参数的request是原来的django原生的request
		#下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
		request = self.initialize_request(request, *args, **kwargs)
		# self 是视图类的对象,视图类对象.request=request 新的request
		self.request = request
		try:
			# 执行了认证,频率,权限 [不读]
			self.initial(request, *args, **kwargs)
			# 原来的View的dispatch的东西
			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 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

3 Request类源码分析

#1  视图类中使用的request对象,已经变成了drf提供的Request类的对象了
	-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
	-drf的request是这个类的对象:rest_framework.request.Request
    
#2 request已经不是原来的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)
        
	-以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
    
	-新的request内部有个老的request,就是 request._request
    
	-data 是个方法,被property装饰了,变成了数据属性用
		-以后body体中提交的数据,都从这里取(request.POST)
		-urlencoded,form-data:提交的数据在request.POST中
		-json格式提交的数据,在requets.POST中没有,它在request.body中
		-现在无论那种格式,都从request.data中取
	-query_params:get请求提交的参数,等同于request._request.GET 或  request.GET
	-其他:取文件也是从request.FILES中取,跟之前一样
    
    
    
# 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据
    
# request.data  有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典
    
# 4 什么是魔法方法?
	1 在类中只要以__开头,__结尾的都称之为魔法方法
    2 这种方法不需要手动调用,某种情况会自动触发
    3 你学过的: __init__,__str__,__call__,......

4 序列化组件介绍

#是什么?drf提供的一个类,我们继承它,写自己的类
# 有什么用?就是用来序列化qs或单个对象的

# 获取所有图书接口----》qs,单个book对象转成json格式字符串,给前端---》序列化
	-使用for循环,列表套字典拼接的
  
  
# drf提供了一种可以快速实现序列化的类:序列化类

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

5.1 定义一个序列化类

# 写序列化类:给book进行序列化
# from rest_framework.serializers import Serializer
from rest_framework import serializers


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

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

class BookView(APIView):  # APIView继承自django的View
    def get(self, request):
        book_list = Book.objects.all()
        # instance表示要序列化的数据,many=True表示序列化多条(instance是qs对象,一定要传many=True)
        ser = BookSerializer(instance=book_list, many=True)

        return Response(ser.data)

5.3 使用序列化类,序列化单挑数据

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

6 反序列化(新增,修改)

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

6.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有值执行update,没有值执行create
            return Response(ser.data)
        else:
            return Response(ser.errors)

序列化类

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

    # 重写create方法,
    def create(self, validated_data):
        res = Book.objects.create(**validated_data)
        return res

6.2修改

视图类

class BookDetailView(APIView):
	def put(self,request,pk):
		book = Book.object.filter(pk=pk).first()
		#前端传递数据,从request.data取出来
		ser = BookSerializer(instance=book,data=requset.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.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()

    # 重写update
    def update(self, instance, validated_data):
        # instance要修改的对象
        # validated_data 校验过后的数据
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()
        return instance

__EOF__

本文作者夏の嵐
本文链接https://www.cnblogs.com/xzljm/p/16732546.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   夏之岚  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示