1. 程式人生 > >Django rest framework(6)----序列化

Django rest framework(6)----序列化

目錄

序列化

1.繼承Serializer

基本使用 

(1)models.py

from django.db import models

class UserInfo(models.Model):
    USER_TYPE = (
        (1,'普通使用者'),
        (2,'VIP'),
        (3,'SVIP')
    )

    user_type = models.IntegerField(choices=USER_TYPE)
    username = models.CharField(max_length=32,unique=True)
    password 
= models.CharField(max_length=64) group = models.ForeignKey('UserGroup',on_delete=models.CASCADE) roles = models.ManyToManyField('Role') class UserToken(models.Model): user = models.OneToOneField('UserInfo',on_delete=models.CASCADE) token = models.CharField(max_length=64)
class UserGroup(models.Model): title = models.CharField(max_length=32) class Role(models.Model): title = models.CharField(max_length=32)

新增Role

(2)api/urls.py

urlpatterns = [
    re_path('(?P<version>[v1|v2]+)/roles/', RolesView.as_view()),   #序列化
]

(3)views.py

import
json from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from . import models from rest_framework import serializers #要先寫一個序列化的類 class RolesSerializer(serializers.Serializer): #Role表裡面的欄位id和title序列化 id = serializers.IntegerField() title = serializers.CharField() class RolesView(APIView): def get(self,request,*args,**kwargs): # 方式一:對於[obj,obj,obj] # (Queryset) roles = models.Role.objects.all() # 序列化,兩個引數,instance:接受Queryset(或者物件) mangy=True表示對Queryset進行處理,mant=False表示對物件進行進行處理 ser = RolesSerializer(instance=roles,many=True) # 轉成json格式,ensure_ascii=False表示顯示中文,預設為True ret = json.dumps(ser.data,ensure_ascii=False) return HttpResponse(ret)

(4)瀏覽器訪問:http://127.0.0.1:8000/api/v1/roles/

 可以顯示後臺返回的json資料

 (5)方式二

class RolesView(APIView):
    def get(self,request,*args,**kwargs):
        # 方式一:對於[obj,obj,obj]
        # (Queryset)
        # roles = models.Role.objects.all()
        # 序列化,兩個引數,instance:Queryset  如果有多個值,就需要加 mangy=True
        # ser = RolesSerializer(instance=roles,many=True)
        # 轉成json格式,ensure_ascii=False表示顯示中文,預設為True
        # ret = json.dumps(ser.data,ensure_ascii=False)

        # 方式二:
        role = models.Role.objects.all().first()
        ser = RolesSerializer(instance=role, many=False)
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

只獲取一個

進階使用

(1)urls.py

新增一個info

urlpatterns = [
    re_path('(?P<version>[v1|v2]+)/roles/', RolesView.as_view()),   #序列化
    re_path('(?P<version>[v1|v2]+)/info/', UserInfoView.as_view()),   #序列化
]

(2)views.py

class UserInfoSerializer(serializers.Serializer):
    '''序列化使用者的資訊'''
    #user_type是choices(1,2,3),顯示全稱的方法用source
    type = serializers.CharField(source="get_user_type_display")
    username = serializers.CharField()
    password = serializers.CharField()
    #group.title:組的名字
    group = serializers.CharField(source="group.title")
    #SerializerMethodField(),表示自定義顯示
    #然後寫一個自定義的方法
    rls = serializers.SerializerMethodField()

    def get_rls(self,row):
        #獲取使用者所有的角色
        role_obj_list = row.roles.all()
        ret = []
        #獲取角色的id和名字
        #以字典的鍵值對方式顯示
        for item in role_obj_list:
            ret.append({"id":item.id,"title":item.title})
        return ret

class UserInfoView(APIView):
    '''使用者的資訊'''
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserInfoSerializer(instance=users,many=True)
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

自定義方法

 (3)瀏覽器訪問:http://127.0.0.1:8000/api/v1/info/

2.繼承 ModelSerializer

把上面的UserInfoSerializer改成繼承ModelSerializer的用法

# class UserInfoSerializer(serializers.Serializer):
#     '''序列化使用者的資訊'''
#     #user_type是choices(1,2,3),顯示全稱的方法用source
#     type = serializers.CharField(source="get_user_type_display")
#     username = serializers.CharField()
#     password = serializers.CharField()
#     #group.title:組的名字
#     group = serializers.CharField(source="group.title")
#     #SerializerMethodField(),表示自定義顯示
#     #然後寫一個自定義的方法
#     rls = serializers.SerializerMethodField()
#
#     def get_rls(self,row):
#         #獲取使用者所有的角色
#         role_obj_list = row.roles.all()
#         ret = []
#         #獲取角色的id和名字
#         #以字典的鍵值對方式顯示
#         for item in role_obj_list:
#             ret.append({"id":item.id,"title":item.title})
#         return ret


class UserInfoSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source="get_user_type_display")
    group = serializers.CharField(source="group.title")
    rls = serializers.SerializerMethodField()

    def get_rls(self, row):
        # 獲取使用者所有的角色
        role_obj_list = row.roles.all()
        ret = []
        # 獲取角色的id和名字
        # 以字典的鍵值對方式顯示
        for item in role_obj_list:
            ret.append({"id": item.id, "title": item.title})
        return ret

    class Meta:
        model = models.UserInfo
        fields = ['id','username','password','type','group','rls']

class UserInfoView(APIView):
    '''使用者的資訊'''
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserInfoSerializer(instance=users,many=True)
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

結果一模一樣

3.自動序列化連表(depth)

繼續優化上面的程式碼,用depth更簡單方便

class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        #fields = "__all__"
        fields = ['id','username','password','group','roles']
        #表示連表的深度
        depth = 1


class UserInfoView(APIView):
    '''使用者的資訊'''
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserInfoSerializer(instance=users,many=True)
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

訪問:http://127.0.0.1:8000/api/v1/info/

4.生成url

url.py

urlpatterns = [
    re_path('(?P<version>[v1|v2]+)/group/(?P<pk>\d+)/', GroupView.as_view(),name = 'gp')    #序列化生成url
]

views.py

class UserInfoSerializer(serializers.ModelSerializer):
    group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='pk')
    class Meta:
        model = models.UserInfo
        #fields = "__all__"
        fields = ['id','username','password','group','roles']
        #表示連表的深度
        depth = 0


class UserInfoView(APIView):
    '''使用者的資訊'''
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        #這裡必須要傳引數context={'request':request}
        ser = UserInfoSerializer(instance=users,many=True,context={'request':request})
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)


class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserGroup
        fields = "__all__"

class GroupView(APIView):
    def get(self,request,*args,**kwargs):
        pk = kwargs.get('pk')
        obj = models.UserGroup.objects.filter(pk=pk).first()

        ser = GroupSerializer(instance=obj,many=False)
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

訪問:http://127.0.0.1:8000/api/v1/info/

可以獲取到group的url

5.使用者請求資料驗證

基本驗證

(1)url.py

urlpatterns = [
    re_path('(?P<version>[v1|v2]+)/usergroup/', UserGroupView.as_view(),)    #序列化做驗證
]

(2)views.py

class UserGroupSerializer(serializers.Serializer):
    title = serializers.CharField()

class UserGroupView(APIView):
    def post(self,request,*args, **kwargs):
        ser = UserGroupSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data['title'])
        else:
            print(ser.errors)

        return HttpResponse("使用者提交資料驗證")

用postman傳送正確的資料,後臺可以拿到

傳送空資料,會自動驗證資料的合法性

 自定義驗證規則

 views.py

新增一個自定義驗證

#自定義驗證規則
class GroupValidation(object):
    def __init__(self,base):
        self.base = base

    def __call__(self, value):
        if not value.startswith(self.base):
            message = "標題必須以%s為開頭"%self.base
            raise serializers.ValidationError(message)


class UserGroupSerializer(serializers.Serializer):
    title = serializers.CharField(validators=[GroupValidation('以我開頭'),])    

class UserGroupView(APIView):
    def post(self,request,*args, **kwargs):
        ser = UserGroupSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data['title'])
        else:
            print(ser.errors)

        return HttpResponse("使用者提交資料驗證")

 提交不合法的資料

 後臺報錯

 提交正確的資料