zoukankan      html  css  js  c++  java
  • 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",
            )
     
    序列化嵌套应用
  • 相关阅读:
    程序员小抄大全
    赢在中国“80后30个忠告”
    Eclipse下python插件(pydev)的安装
    PDF加密文件的解密和打印
    中美欧联手打击僵尸网络 深化安全合作 狼人:
    入侵奥巴马帐号法国黑客自称是一个好黑客 狼人:
    Firefox 3.6.3版率先修复黑客大赛所曝漏洞 狼人:
    2009年全球安全SaaS市场收入比2008年增长70% 狼人:
    微软等厂商高管谈安全云面临的挑战 狼人:
    报告称Windows7不安全 管理员权限是罪魁祸首 狼人:
  • 原文地址:https://www.cnblogs.com/open-yang/p/11573494.html
Copyright © 2011-2022 走看看