Django rest framework(6)----序列化
阿新 • • 發佈:2018-12-30
目錄
序列化
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
importjson 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("使用者提交資料驗證")
提交不合法的資料
後臺報錯
提交正確的資料