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('提交数据')

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

 更新中....

猜你喜欢

转载自www.cnblogs.com/Alexephor/p/11306201.html