drf从入门到精通 05

今日内容详细

1.反序列化类校验部分源码解析

# 反序列化校验 什么时候开始执行校验
	-视图类中的 ser.is_valid()  就会开始执行校验 校验通过返回True 不通过返回False
    
    
# 入口:ser.is_valid() 是序列化类的对象,假设序列化类是BookSerializer---> is_valid ---> 找不到  找到父类BaseSerializer中有:【raise_exception:先注意】
	def is_valid(self, *, raise_exception=False):
		if not hasattr(self, '_validated_data'):
			try:
				# self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
				self._validated_data = self.run_validation(self.initial_data)
			except ValidationError as exc:
				self._validated_data = {}
				self._errors = exc.detail
			else:
				self._errors = {}

		if self._errors and raise_exception:
			raise ValidationError(self.errors)

		return not bool(self._errors)
# self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象
	-切记一定不要按住ctrl键点击
	-真正的执行顺序是,从下往上找,找不到,再往上
	-最终从Serializer类中找到了run_validation,而不是Field中的run_validation
	def run_validation(self, data=empty):
		# 字段自己的,validates方法
		(is_empty_value, data) = self.validate_empty_values(data)
		if is_empty_value:
			return data
		# 局部钩子----【局部钩子】
		value = self.to_internal_value(data)
		try:
			self.run_validators(value)
			# 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
			value = self.validate(value)
		except (ValidationError, DjangoValidationError) as exc:
			raise ValidationError(detail=as_serializer_error(exc))
		return value
    
# 局部钩子  self.to_internal_value(data)    ---》self是BookSerializer的对象,从根上找
	def to_internal_value(self, data):
		ret = OrderedDict()
		errors = OrderedDict()
		fields = self._writable_fields
		# fields写在序列化类中一个个字段类的对象
		for field in fields:
			# self BookSerializer的对象,反射validate_name
			validate_method = getattr(self, 'validate_' + field.field_name, None)
			try:
				# 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
				validated_value = validate_method(validated_value)
			except ValidationError as exc:
				errors[field.field_name] = exc.detail
          
			else:
				set_value(ret, field.source_attrs, validated_value)
		if errors:
			raise ValidationError(errors)
		return ret

2.断言

# 源码中大量使用try和断言

# 关键字assert   断定你是xx  如果不是就抛异常

name = 'qyf'
assert name = 'qyf'  #  断定是  如果不是 就抛异常
print('后续代码')

3.drf之请求

Request能够解析的前端传入的编码格式

# 需求是该接口只能接收json格式,不能接收其他格式

# 总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
# 方式一,在继承自APIView及其子类的的视图类中配置(局部配置)
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默认的配置找

4.drf之响应

Response能够响应的编码格式

# drf 是django的一个app  需要注册
# drf的响应 如果使用浏览器和postman访问同一个接口 返回格式是不一样的
	-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',
	],
}

# 使用顺序(一般就用内置的即可)
	优先使用视图类中的配置 其次使用项目配置文件中的配置
最后使用内置的

Response的源码属性或方法

# drf的Response源码分析
	-from rest_framework.response import Response
	-视图类的方法返回时,return Response 走它的__init__
    
# 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响应的响应头
	# 补充:原生django 如何向响应头中加东西
		# 四件套 render,redirect,HttpResponse,JsonResponse
		obj = HttpResponse('dddd')
		obj['xxc'] = 'yyc'
		return obj
	-content_type:响应编码格式 一般不动

5.视图组件介绍及两个视图基类

django rest_framework提供的视图的主要作用:
	控制序列化器的执行(校验、保存、转换数据)
	控制数据库查询的执行
rest_framework提供了众多的通用视图基类与扩展类,以简化视图的编写

# APIView跟之前的View区别
	-传入到视图方法中的是rest_framework的Request对象,而不是Django的HttpRequeset对象;
	-视图方法可以返回rest_framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
	-任何APIException异常都会被捕获到,并且处理成合适的响应信息;
	-在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
    
# 两个视图基类
	APIView
		-类属性:
			renderer_classes  # 响应格式
			parser_classes  # 能够解析的请求格式
			authentication_classes  # 认证类
			throttle_classes  # 频率类
			permission_classes  # 权限类

APIView+ModelSerializer+Resposne写5个接口

视图类

from .models import Book
from .serializer import BookSerializer

class BookView(APIView):
	def get(self, request):
		books = Book.objects.all()
		ser = BookSerializer(instance=books, many=True)
		return Response(ser.data)

	def post(self, request):
		ser = BookSerializer(data=request.data)
		if ser.is_valid():
			ser.save()
			# 咱们现在只有ser序列化类的对象,但是咱们想要,新增对象---> 序列化成字典---> 大前提,序列化类中的create方法一定要返回新增的对象
			return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
		else:
			return Response({'code': 101, 'msg': ser.errors})


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

	def put(self, request, pk):
		books = Book.objects.filter(pk=pk).first()
		ser = BookSerializer(instance=books, data=request.data)
		if ser.is_valid():
			ser.save()
			return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
		else:
			return Response({'code': 101, 'msg': ser.errors})

	def delete(self, request, pk):
		Book.objects.filter(pk=pk).delete()
		return Response({'code': 100, 'msg': '删除成功'})

序列化类

## ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
	# 跟表有关联
	class Meta:
		model = Book
		fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
		extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

路由

urlpatterns = [
	path('admin/', admin.site.urls),
	path('books/', views.BookView.as_view()),
	path('books/<int:pk>/', views.BookDetailView.as_view()),
]

6.基于GenericAPIView+5个视图扩展类

视图类

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, ListModelMixin


# 基于GenericAPIView+5个视图扩展类写接口

class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
	queryset = Book.objects.all()
	serializer_class = BookSerializer

	def get(self, request):
		return self.list(request)

	def post(self, request):
		return self.create(request)


class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
	queryset = Book.objects.all()
	serializer_class = BookSerializer

	def get(self, request, *args, **kwargs):
		return self.retrieve(request, *args, **kwargs)

	def put(self, request, *args, **kwargs):
		return self.update(request, *args, **kwargs)

	def delete(self, request, *args, **kwargs):
		return self.destroy(request, *args, **kwargs)

序列化类

## ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
	# 跟表有关联
	class Meta:
		model = Book
		fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
		extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

路由

urlpatterns = [
	path('admin/', admin.site.urls),
	path('books/', views.BookView.as_view()),
	path('books/<int:pk>/', views.BookDetailView.as_view()),
]
posted @   小白峰  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
点击右上角即可分享
微信分享提示