Django REST framework之序列化组件以及源码分析+全局局部Hook

Posted alexephor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django REST framework之序列化组件以及源码分析+全局局部Hook相关的知识,希望对你有一定的参考价值。

序列化两大功能

  a.对queryset类型进行序列化

  b.对用户请求的数据进行校验

 

a.对queryset类型进行序列化

举例说明:

表设计

 1 from django.db import models
 2 
 3 
 4 class UserGroup(models.Model):
 5     title = models.CharField(max_length=32)
 6 
 7 
 8 class UserInfo(models.Model):
 9     user_type_choices = (
10         (1, 普通用户),
11         (2, vip),
12         (3, svip),
13     )
14     user_type = models.IntegerField(choices=user_type_choices)
15     username = models.CharField(max_length=32, unique=True)
16     password = models.CharField(max_length=64)
17     group = models.ForeignKey(UserGroup, on_delete=models.CASCADE)
18     roles = models.ManyToManyField(Role)
19 
20 
21 class UserToken(models.Model):
22     user = models.OneToOneField(to=UserInfo, on_delete=models.CASCADE)
23     token = models.CharField(max_length=64)
24 
25 
26 class Role(models.Model):
27     title = models.CharField(max_length=32)

总路由:

1 from django.contrib import admin
2 from django.urls import path, re_path, include
3 
4 urlpatterns = [
5     path(admin/, admin.site.urls),
6     re_path(api/, include(api.urls)),
7 ]

 

分发:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.urls import path, re_path, include
from api import views

urlpatterns = [

    # 序列化
    re_path((?P<version>[v1|v2]+)/roles/$, views.RolesView.as_view()),
    re_path((?P<version>[v1|v2]+)/userinfo/$, views.UserInfoView.as_view()),
    # 序列化并生成url查看详情restful返回链接
    re_path((?P<version>[v1|v2]+)/group/(?P<pk>\d+)$, views.GroupView.as_view(), name=group),
    # 验证
    re_path((?P<version>[v1|v2]+)/usergroup/$, views.UserGroupView.as_view()),

]

 

视图初探  继承serializers.Serializer   版本1  字段初探

 1 import json
 2 from django.shortcuts import render, HttpResponse
 3 from rest_framework import serializers
 4 from api import models
 5 
 6 
 7 class RolesSerializer(serializers.Serializer):
 8     id = serializers.IntegerField()
 9     title = serializers.CharField()
10 
11 
12 class RolesView(APIView):
13 
14     def get(self, request, *args, **kwargs):
15         # 方式1
16         # roles = models.Role.objects.all().values(‘id‘, ‘title‘)
17         # roles = list(roles)
18         # ret = json.dumps(roles, ensure_ascii=False)
19         # 方式2
20         # roles = models.Role.objects.all()
21         # ser = RolesSerializer(instance=roles, many=True)
22         # ret = json.dumps(ser.data, ensure_ascii=False)
23 
24         role = models.Role.objects.all().first()
25         ser = RolesSerializer(instance=role, many=False)
26         ret = json.dumps(ser.data, ensure_ascii=False)
27         return HttpResponse(ret)

 

继承serializers.Serializer 版本2 进阶对序列类字段着手

 1 class UserInfoSerializer(serializers.Serializer):
 2     # user_type = serializers.IntegerField()
 3     uuu = serializers.CharField(source=user_type)
 4     # 显示用户类型get_user_type_display内部是否callable若能直接调用,不能就直接返回
 5     ooo = serializers.CharField(source=get_user_type_display)
 6     username = serializers.CharField()
 7     password = serializers.CharField()
 8     # 显示用户组名称
 9     gp = serializers.CharField(source=group.title)
10     # 显示用户在的所有组
11     # roles = serializers.CharField(source=‘roles.all‘) # 力度不够
12     # 处理ManyToManyField字段
13     role = serializers.SerializerMethodField()
14     
15     def get_role(self, row):
16         role_obj_list = row.roles.all()
17         ret = []
18         for item in role_obj_list:
19             ret.append(id: item.id, title: item.title)
20         return ret

继承serializers.ModelSerializer 版本3 对字段着手

 1 class UserInfoSerializer(serializers.ModelSerializer):
 2     ooo = serializers.CharField(source=get_user_type_display)
 3     # Serializer(BaseSerializer, metaclass=SerializerMetaclass)
 4     # ModelSerializer(Serializer)
 5     role = serializers.SerializerMethodField()
 6 
 7     class Meta:
 8         model = models.UserInfo
 9         # fields = ‘__all__‘
10         fields = [id, username, password, ooo, role,  group]
11 
12     def get_role(self, row):
13         role_obj_list = row.roles.all()
14         ret = []
15         for item in role_obj_list:
16             ret.append(id: item.id, title: item.title)
17         return ret

深度自动连表操作

1 class UserInfoSerializer(serializers.ModelSerializer):
2     # ooo = serializers.CharField(source=‘get_user_type_display‘)
3     # Serializer(BaseSerializer, metaclass=SerializerMetaclass)
4     # ModelSerializer(Serializer)
5 
6     class Meta:
7         model = models.UserInfo
8         fields = __all__
9         depth = 1  # 官方0~10 自我感觉最多2层,层数多响应数据慢

 

返回json数据中给用户提供链接字段

 1 class UserInfoSerializer(serializers.ModelSerializer):
 2     # ooo = serializers.CharField(source=‘get_user_type_display‘)
 3     # Serializer(BaseSerializer, metaclass=SerializerMetaclass)
 4     # ModelSerializer(Serializer)
 5     # 生成url查看用户组详情链接restful规范在实例化时候必须加上context=‘request‘: request字段
 6     group = serializers.HyperlinkedIdentityField(view_name=group, lookup_field=group_id, lookup_url_kwarg=pk)
 7 
 8     class Meta:
 9         model = models.UserInfo
10         fields = __all__
11         depth = 1  # 官方0~10 自我感觉最多2层倒是行了
12 
13 
14 class UserInfoView(APIView):
15     def get(self, request, *args, **kwargs):
16         """
17         取数据序列化
18         :param request:
19         :param args:
20         :param kwargs:
21         :return:
22         """
23         users = models.UserInfo.objects.all()
24         ser = UserInfoSerializer(instance=users, many=True, context=request: request)
25         ret = json.dumps(ser.data, ensure_ascii=False)
26         return HttpResponse(ret)

 

在页面显示提供url链接地址

 1 class GroupSerializer(serializers.ModelSerializer):
 2     class Meta:
 3         model = models.UserGroup
 4         fields = __all__
 5 
 6 
 7 class GroupView(APIView):
 8     def get(self, request, *args, **kwargs):
 9         pk = kwargs.get(pk)
10         obj = models.UserGroup.objects.filter(pk=pk).first()
11         ser = GroupSerializer(instance=obj, many=False)
12         return HttpResponse(json.dumps(ser.data, ensure_ascii=False))

 

 

b.对用户请求数据进行校验

自定义验证规则validators+钩子

 1 class XValidator(object):
 2     def __init__(self, base):
 3         self.base = base
 4 
 5     def __call__(self, value):
 6         if not value.startswith(self.base):
 7             message = 必须以%s 开头 % self.base
 8             raise serializers.ValidationError(message)
 9 
10     def set_context(self, serializer_field):
11         """
12         This hook is called by the serializer instance,
13         prior to the validation call being made.
14         """
15         # 执行验证之前调用,serializer_fields是当前字段对象
16         pass
17 
18 
19 class UserGroupSerializer(serializers.Serializer):
20     title = serializers.CharField(error_messages=required: 不能为空, validators=[XValidator(字母或者下划线), ])
21     # 局部钩子
22     
23     def validate_title(self, value):
24         from rest_framework.exceptions import ValidationError
25         print(value)
26         # raise ValidationError(‘仇恨有点大,不让你通过‘)
27         return value
28     # 全局钩子
29     
30     def validate(self, attrs):
31         print(attrs)
32         return attrs
33 
34 
35 class UserGroupView(APIView):
36     def post(self, request, *args, **kwargs):
37         ser = UserGroupSerializer(data=request.data)
38         if ser.is_valid():
39             print(ser.validated_data[‘title‘])
40         else:
41             print(ser.errors)
42 
43         return HttpResponse(提交数据)

 序列化源码分析+钩子源码分析

 更新中....

 

以上是关于Django REST framework之序列化组件以及源码分析+全局局部Hook的主要内容,如果未能解决你的问题,请参考以下文章

Django REST framework框架之GET, POST, PUT, PATCH, DELETE等API请求接口设计

Django:rest framework之分页(Pagination)

rest framework 之序列化

django之序列化数据

django之序列化数据

django-rest-framework:如何序列化已经包含 JSON 的字段?