DRF序列化組件

1.DRF序列化器Serializerpython

  

 

 

   models.py:  django

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  json

    drf主路由配置urls.py  api

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

    api路由配置urls.py:  session

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:  app

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  ide

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深度序列化  post

  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",
        )
 
序列化嵌套應用
相關文章
相關標籤/搜索