DRF序列化组件

1.DRF序列化器Serializer

  

 

 

   models.py:  

from django.db import models
 
class UserInfo(models.Model):
    """
    用户表
    """
    user_type_choices = [
        (1, '普通用户'),
        (2, 'VIP用户'),
        (3, 'SVIP用户'),
    ]
    user_type = models.IntegerField(choices=user_type_choices)
    username = models.CharField(max_length=10, unique=True)
    password = models.CharField(max_length=12, null=False)
 
    group = models.ForeignKey(to='UserGroup')
    role = models.ManyToManyField(to='UserRole')
 
 
class UserToken(models.Model):
    """
    token表
    """
 
    user = models.OneToOneField(to='UserInfo')
    token = models.CharField(max_length=64)
    create_time = models.DateTimeField(auto_now=True)
 
 
class UserGroup(models.Model):
    title = models.CharField(max_length=10)
 
 
class UserRole(models.Model):
    role = models.CharField(max_length=12)
models.py:

  urls.py  

    drf主路由配置urls.py  

from django.conf.urls import url,include
urlpatterns = [
    url(r'^api/', include('api.urls')),
]
drf主路由配置urls.py:

    api路由配置urls.py:  

from django.conf.urls import url
from api import views
 
urlpatterns = [
    url(r'^(?P<version>v[\d+])/users/', views.UsersView.as_view(), name='users'),
    url(r'^(?P<version>v[\d+])/parsers/', views.ParsersView.as_view(), name='parsers'),
    url(r'^(?P<version>v[\d+])/userroles/', views.UserRole.as_view(), name='userrole'),
    url(r'^(?P<version>v[\d+])/userinfos/', views.UserInfoView.as_view(), name='userinfo'),
]
api路由配置urls.py:

  views.py:  

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework.versioning import BaseVersioning, QueryParameterVersioning, URLPathVersioning
from django.urls import reverse
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser
from django.http.response import JsonResponse
from rest_framework import serializers
from api import models
import json
 
 
class UsersView(APIView):
    # API版本组件(局部配置)----返回结果都是一样
    # 也需要在settings.py中的REST_FRAMEWORK进行全局配置
    '''
        default_version = api_settings.DEFAULT_VERSION
        allowed_versions = api_settings.ALLOWED_VERSIONS
        version_param = api_settings.VERSION_PARAM
    '''
 
    # (1)当版本号以查询参数形式传递时:比如:http://127.0.0.1:8000/api/users/?version=v1
    # (推荐第2种方式,此方式url(r'^/users/',views.UsersView.as_view(),name='users'),)
    # versioning_class = QueryParameterVersioning
 
    # (2)当版本号以路径urlpath形式传递时:比如:http://127.0.0.1:8000/api/v1/users/
    # (注意在urls.py中使用正则匹配url(r'^(?P<version>v[\d+])/users/',views.UsersView.as_view(),name='users'),)
    # versioning_class = URLPathVersioning
 
    def get(self, request, *args, **kwargs):
        print(request.version)  # 获取版本号
        print(request.versioning_scheme)  # 获取到版本号处理的类对象,封装了reverse方法
        print(request.versioning_scheme.reverse(viewname='users', request=request))  # 反向解析url
        # print(reverse(viewname='users',kwargs={'version':request.version}))#django原生解析,必须指定参数
 
        return HttpResponse('get_users')
 
    def post(self, request, *args, **kwargs):
        return HttpResponse('post_user')
 
 
class ParsersView(APIView):
    # 解析器组件(局部配置)----不配置默认全都支持
    parser_classes = [FormParser]
    '''
    from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
        JSONParser:'application/json'
      FormParser:'application/x-www-form-urlencoded'
      MultiPartParser:'multipart/form-data'
        FileUploadParser:'*/*'
    '''
 
    def post(self, request, *args, **kwargs):
        print(request.POST)
        # 1.获取请求
        print(request.data)
 
        return HttpResponse('DRF解析器测试')
 
 
# (1)自定义序列化器继承serializers.Serializer的简单使用
class UserRoleSerializer(serializers.Serializer):
    '''
    角色序列化器
    '''
    pk = serializers.IntegerField()
    role = serializers.CharField()
 
 
class UserRole(APIView):
    '''
    自定义序列化器的简单使用
    '''
 
    def get(self, request, *args, **kwargs):
        '''
        显示所有的角色信息,以字符串形式返回
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        # 方式一:手动序列化
        '''
        #json不能序列化django中的QuerySet类型数据,需要转换python支持的数据类型在序列化
        ret = models.UserRole.objects.all().values('pk','role')
        ret =json.dumps(list(ret),ensure_ascii=False)
        '''
 
        # 方式二:drf中的序列化器组件
        query_set = models.UserRole.objects.all()
        ret_serializer = UserRoleSerializer(instance=query_set, many=True)  # 序列化多条数据时指定many=True,单条数据指定many=False
        # query_set = models.UserRole.objects.all().first()
        # ret_serializer = UserRoleSerializer(instance=query_set, many=False)
        ret = json.dumps(ret_serializer.data, ensure_ascii=False)
 
        return HttpResponse(ret)
 
 
# (2)自定义序列化器继承serializers.Serializer的详解
class UserInfoSerializer(serializers.Serializer):
    # (1)序列化表中对应的字段,字段名要和表字段对应
    # user_type = serializers.IntegerField()  #显示表中存储的数字
    username = serializers.CharField()
    # password = serializers.CharField()
 
    # (2)序列化表中的choice字段,需要使用source参数结合get_field_display方法(方法会自动调用)
    user_type = serializers.CharField(source="get_user_type_display")
 
    # (3)使用表中不存在字段来序列化表字段时需要使用source参数指定源数据
    pwd = serializers.CharField(source="password")
 
    # (4)序列化外键字段(多对一)使用source参数指定源数据(外键字段的.方法)
    group = serializers.CharField(source="group.title")
 
    # (5)序列化多对多字段(数据多个需要使用)
    role = serializers.SerializerMethodField()
 
    def get_role(self, instance):  # 第二个参数instance是当前对象
        query_set = instance.role.all()
        ret = [{'pk': obj.pk, 'role': obj.role} for obj in query_set]
        return ret
 
 
class UserInfoView(APIView):
    def get(self, requeat, *args, **kwargs):
        query_set = models.UserInfo.objects.all()
        ret_serializer = UserInfoSerializer(instance=query_set, many=True)# 序列化多条数据时指定many=True,单条数据指定
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
views.py:

  settings.py  

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api.apps.ApiConfig',
    'rest_framework',
]
 
REST_FRAMEWORK = {
    #版本组件(全局配置)----在认证+权限+节流之前
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',#设置版本组件类
    'DEFAULT_VERSION':'v1',#默认的API版本
    'ALLOWED_VERSIONS':['v1','v2'],#允许的API版本
    'VERSION_PARAM':'version',#版本的key,默认的就是version(注意要和api接口中的key对应)
 
#解析器组件
'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser',],#可指定多个解析器,不配置默认支持所有
 
}
 
settings.py

2. DRF序列化器ModelSerializer  

基于上述的案例实现
 
# 自定义序列化器继承serializers.Serializer的详解
'''
class UserInfoSerializer(serializers.Serializer):
    # (1)序列化表中对应的字段,字段名要和表字段对应
    # user_type = serializers.IntegerField()  #显示表中存储的数字
    username = serializers.CharField()
    # password = serializers.CharField()
 
    # (2)序列化表中的choice字段,需要使用source参数结合get_field_display方法
    user_type = serializers.CharField(source="get_user_type_display")
 
    # (3)使用表中不存在字段来序列化表字段时需要使用source参数指定源数据
    pwd = serializers.CharField(source="password")
 
    # (4)序列化外键字段(多对一)使用source参数指定源数据(外键字段的.方法)
    group = serializers.CharField(source="group.title")
 
    # (5)序列化多对多字段(数据多个需要使用)
    role = serializers.SerializerMethodField()
 
    def get_role(self, instance):  # 第二个参数instance是当前对象
        query_set = instance.role.all()
        ret = [{'pk': obj.pk, 'role': obj.role} for obj in query_set]
        return ret
'''
 
#自定义序列化器继承serializers.ModelSerializer类(基于model表对象实现)
class UserInfoSerializer(serializers.ModelSerializer):
 
    # (1)定义元类Meta指定model和fields,自动映射表中的字段,还可自定义字段
    class Meta:
        model= models.UserInfo#指定model表对象
        # fields = "__all__"#设置所有字段
        fields = ['pk','user_type','username','pwd','group_title','role_list']#指定字段(可以定制)
 
    # (2)表中choice字段
    user_type = serializers.CharField(source='get_user_type_display')
    # (3)表中字段修改名
    pwd = serializers.CharField(source='password')
    # (4)外键多对一字段
    group_title = serializers.CharField(source='group.title')
 
    # (5)多对多的多字段
    role_list = serializers.SerializerMethodField()
    def get_role_list(self, instance):  # 第二个参数instance是当前对象
        query_set = instance.role.all()
        ret = [{'pk': obj.pk, 'role': obj.role} for obj in query_set]
        return ret
 
class UserInfoView(APIView):
    def get(self, requeat, *args, **kwargs):
        query_set = models.UserInfo.objects.all()
        ret_serializer = UserInfoSerializer(instance=query_set, many=True)# 序列化多条数据时指定many=True,单条数据指定many=False
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
ModelSerializers

3.DRF序列化器depth深度序列化  

  DRF序列化器ModelSerializer基于参数depth深度序列化  

#自定义序列化器继承serializers.ModelSerializer类(基于model表对象实现,集合参数depth实现表关联字段的的数据序列化)
class UserInfoSerializer(serializers.ModelSerializer):
 
    class Meta:
        model= models.UserInfo#指定model表对象
        # fields = "__all__"#设置所有字段
        fields = ['pk','user_type','username','password','group','role']#指定字段(可以定制)
        depth = 1#序列化深度指定,默认为0,建议在0-10,可以深度序列化表字段数据
 
 
class UserInfoView(APIView):
    def get(self, requeat, *args, **kwargs):
        query_set = models.UserInfo.objects.all()
        ret_serializer = UserInfoSerializer(instance=query_set, many=True)
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
depth参数深度序列化

4.DRF序列化器返回url链接 

  遵循RESTful规范中的Hypermedia API(返回有带url结果)

  urls.py

    drf主路由配置urls.py

from django.conf.urls import url,include
urlpatterns = [
    url(r'^api/', include('api.urls')),
]
drf主路由配置urls.py:

    api路由配置urls.py:

from django.conf.urls import url
from api import views
#版本控制组件在settings.py中
urlpatterns = [
    url(r'^(?P<version>v[\d+])/userinfos/', views.UserInfoView.as_view(), name='userinfo'),
    url(r'^(?P<version>v[\d+])/group/(?P<pk>\d+)/', views.UserGroupView.as_view(), name='group'),
]
api路由配置urls.py:

  views.py:  

from rest_framework.views import APIView
from django.http.response import JsonResponse
from rest_framework import serializers
from api import models
 
# 自定义序列化器继承serializers.ModelSerializer类(在序列化结果中返回url)
class UserInfoSerializer(serializers.ModelSerializer):
#
# 指定别名和参数lookup_url_kwarg以及参数对应的值lookup_field,通过反向解析生成,在使用序列化器时必须加上参数,context={'request': request} 
#view_name是别名,lookup_field是指定的值,lookup_url_kwarg指定的参数
group = serializers.HyperlinkedIdentityField(view_name='group',lookup_field='group_id',lookup_url_kwarg='pk')  
    class Meta:
        model = models.UserInfo
        fields = ['pk', 'user_type', 'username', 'password', 'group', 'role']
        depth = 1
 
class UserInfoView(APIView):
    def get(self, request, *args, **kwargs):
        query_set = models.UserInfo.objects.all()
        # 注意在序列化器中使用HyperlinkedIdentityField是必须在序列化时加上context={'request': request}
        ret_serializer = UserInfoSerializer(instance=query_set, many=True, context={'request': request})
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
 
 
class UserGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserGroup
        fields = "__all__"
 
class UserGroupView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        obj = models.UserGroup.objects.filter(pk=pk).first()
        ret_serializer = UserGroupSerializer(instance=obj, many=False)
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
 
 
views.py:

5. DRF序列化器的校验功能

  DRF序列化器的校验可以对比form校验来使用,基本类似,也可定义字段的校验,校验参数、自定义函数以及钩子

class UserGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserGroup
        fields = "__all__"
 
 
class UserGroupView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        obj = models.UserGroup.objects.filter(pk=pk).first()
        ret_serializer = UserGroupSerializer(instance=obj, many=False)
        ret = ret_serializer.data
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})  # 序列化时确保中文正常显示
 
    def post(self, request, *args, **kwargs):
        data = request.data
        ret = UserGroupSerializer(data=data)#基于序列化器的校验
        if ret.is_valid():
            print(ret.validated_data)
        else:
            print(ret.errors)
        return JsonResponse(data)
自校验
数据校验
基本校验
class Parent(serializers.Serializer):
    # required 这个字段是否必传
    # allow_blank 是否允许这个字段为 空值
    # allow_null  是否允许这个字段为 null值
#定义error_messages={},validators=[]进行错误处理和校验,类比form
    value = serializers.CharField(required=True, allow_blank=True, allow_null=True)
 
钩子校验
class Child(serializers.Serializer):
    name = serializers.CharField(required=True)
 
    # 数据校验之前 可以获取到原始数据的方法
    def to_internal_value(self, data):
        return data
 
    # 局部钩子
    def validate_name(self, value):
        return value
 
    # 全局钩子
    def validate(self, data):
        return data
 
 
class Parent(serializers.Serializer):
    value = serializers.CharField(required=True, allow_blank=True, allow_null=True)
    children = serializers.ListSerializer(child=Child())
 
$ data = {"value": "sdf", "children": [{"name": "", }, {"name": "哈哈哈"}]}
$ ser = Parent(data=data)
$ ser.is_valid()
False
$ ser.errors
{'children': [{'name': [ErrorDetail(string='This field may not be blank.', code='blank')]}, {}]}
$ data = {"children": [{"name": "", }, {"name": "哈哈哈"}]}
$ ser = Parent(data=data)
$ ser.is_valid()
False
$ ser.errors
{'value': [ErrorDetail(string='This field is required.', code='required')],
 'children': [{'name': [ErrorDetail(string='This field may not be blank.', code='blank')]}, {}]}
钩子校验

6.DRF序列化器的嵌套  

  序列化器嵌套示例 

# 针对于 多对多 数据 正向反向的数据操作
 
from rest_framework import serializers
 
data = {'id': 1, 'children': [{'id': 2}, {'id': 3}]}
 
class Child(serializers.Serializer):
    id = serializers.IntegerField()
 
class Parent(serializers.Serializer):
    id = serializers.IntegerField()
    children = serializers.ListSerializer(child=Child())#子序列化器
 
'''
# 另一种写法
class Parent(serializers.Serializer):
    id = serializers.IntegerField()
    childs = Child(many=True, source='children')#表中的指向的多字段
'''
 
print(Parent(data).data)
 
序列化器嵌套示例

    序列化嵌套应用

class SurveyChoiceSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = models.SurveyChoice
        fields = "__all__"
 
 
class SurveyQuestionSerializer(serializers.ModelSerializer):
 
    # 第一种方式
    # choices = serializers.SerializerMethodField()
    # def get_choices(self, instance):
    #     return list(instance.surveychoice_set.values())
 
    # 第二种方式
    choices = SurveyChoiceSerializer(many=True, source="answers")#多对多的字段
    value = serializers.CharField(default="")
 
    class Meta:
        model = models.SurveyQuestion
        fields = (
            "id",
            "survey_type",
            "title",
            "choices",
            "value",
        )
 
 
class SurveyTemplateSerializer(serializers.ModelSerializer):
    # 层层递交
    questions = SurveyQuestionSerializer(many=True)
 
    class Meta:
        model = models.SurveyTemplate
        fields = (
            "id",
            "name",
            "questions",
        )
 
 
class SurveyDetailSerializer(serializers.ModelSerializer):
   # 交给子级序列化器渲染
    survey_templates = serializers.ListSerializer(child=SurveyTemplateSerializer())
 
    class Meta:
        model = models.Survey
        fields = (
            "id",
            "survey_templates",
        )
 
序列化嵌套应用

 

posted @ 2019-09-23 17:20  笑得好美  阅读(337)  评论(0编辑  收藏  举报