"""一、Serializer類:底層序列化-瞭解的類 重點:單表序列化 二、modelSerializer類:模型序列化類-核心類 重點:多表序列化 三、ListSerializer類:羣操做序列化類-輔助類 重點:輔助完成單表多表羣增羣改操做""" import sys # 標準輸出流 sys.stdout.write('123\n') sys.stdout.write('456\n') # 標準輸入流 res=sys.stdin.readline() print(res) # 標準錯誤流 sys.stderr.write('jdjf\n') sys.stderr.write('hsh\n') 內部類: def fn(): def func(): pass class A: class B: # B類的名稱能夠經過A類來訪問 x = 10 y = 20 print(A.B.x) # 10
一、設置序列化字段,字段名與字段類型要處理的model類對應(只參與序列化的類型不須要設置條件)
二、model類中有的字段,可是序列化中沒前端
有對應字段,該字段不參加序列化
三、自定義序列化字段(方法一),字段類型爲SerializerMethodField(),值有get_自定義字段名(self, obj)方法提供,通常值都與參與序列化的model對象(model_obj)有關數據庫
from rest_framework import serializers from django.conf import settings from . import models class UserSerializer(serializers.Serializer): # 1)字段名與字段類型要處理的model類對應 # 2)不提供的字段,就不參與序列化給前臺 # 3)能夠自定義序列化字段,採用方法序列化,方法固定兩個參數,第二個參數就是參與序列化的model對象 # (嚴重不建議自定義字段與數據庫字段重名,由get_自定義字段名方法的返回值提供字段值) usernamae = serializers.CharField() # sex=serializers.SerializerMethodField()不建議這樣命名 gender = serializers.SerializerMethodField() def get_gender(self, obj): return obj.get_sex_display() # 返回的值給gender # 注:在高級序列化與高級視圖類中,drf默認幫咱們處理圖片等子資源 icon = serializers.SerializerMethodField() def get_icon(self, obj): return '%s%s%s' % (settings.BASE_URL, settings.MEDIA_URL, obj.img)
# 單查羣查 #視圖類序列化過程 #1)ORM操做獲得數據 #2)將數據序列化成能夠返回給前臺的數據 #3)返回數據給前臺 def get(self,request,*args,**kwargs): pk=kwargs.get('pk') if pk: user_obj=models.User.objects.filter(is_delete=False,pk=pk).first() if not user_obj: return Response({ 'status':1, 'msg':'pk error', },status=400) user_ser=serializers.UserSerializer(user_obj,many=False)#將從數據庫查到的數據對象傳進去,many默認爲False,單查,返回的也是一個類實例化的對象 user_obj_data=user_ser.data return Response({ 'status':0, 'msg':'ok', 'results':user_obj_data }) else: #將對象對外提供的字段,已經整個序列化過程封裝,造成序列化類 user_query=models.User.objects.filter(is_delete=False).all() user_ser=serializers.UserSerializer(user_query,many=True)#將從數據庫查到的query對象傳進去,many爲True,羣查,返回的也是一個類實例化的對象 user_list_data=user_ser.data return Response({ 'status': 0, 'msg': 'ok', 'results': user_list_data })
#單增 #視圖類反序列化過程 #1)從請求對象中獲取前臺提交的數據 #2)交給序列化類完成反序列化(數據的校驗) #3)藉助序列化類完成數據入庫 #4)反饋給前臺處理結果 def post(self,request,*args,**kwargs): request_data=request.data#取出前端傳來的數據 user_ser=serializers.UserDeSerializer(data=request_data) if user_ser.is_valid(): #入庫 user_obj=user_ser.save() return Response({ 'status':0, 'msg':'ok', 'results':serializers.UserSerializer(user_obj).data#將入庫獲得的user對象從新序列化的數據返回給前臺 }) else: return Response({ 'status': 1, 'msg': user_ser.errors, })
一、系統校驗字段與自定義校驗字段定義沒有區別:字段 = serializers.字段類型(條件)
二、自定義校驗字段是不能直接入庫的,須要設置入庫規則,或將其移除不入庫(這類字段就是參與全局校驗用的)
三、全部字段均可以設置對應局部鉤子進行校驗,鉤子方法 validate_字段名(self, 字段值value)
規則:成功直接返回value,失敗拋出校驗失敗信息ValidationError('錯誤信息')
四、一個序列化類存在一個全局鉤子能夠對全部字段進行全局校驗,鉤子方法 validate(self, 全部字段值字典attrs)
規則:成功直接返回attrs,失敗拋出校驗失敗信息ValidationError({'異常字段', '錯誤信息'})
五、重寫create方法實現增入庫,返回入庫成功的對象
六、重寫update方法實現改入庫,返回入庫成功的對象django
class UserDeSerializer(serializers.Serializer): # 系統校驗字段 usernamae = serializers.CharField(min_length=3, max_length=16, error_messages={ 'min_length': '過短', 'max_length': '太長' }) password = serializers.CharField(min_length=3, max_length=16) # 不寫,不參加反序列化,寫了就必須參加反序列化(但能夠設置required=False取消必須) # required=False的字段,前臺不提供,走默認值,提供就必定進行校驗,不寫前臺不提供都採用默認值 sex = serializers.BooleanField(required=False) # 自定義校驗字段:其設置語法與系統字段沒有區別,可是這些字段不能參與入庫操做,須要在全局鉤子中,將其取出 re_password = serializers.CharField(min_length=3, max_length=16) # 局部鉤子 # 方法就是validate_校驗的字段名(self,校驗的字段數據) # 校驗規則:成功直接返回value,失敗跑出校驗失敗信息 def validate_usernamae(self, value): if 'g' in value.lower(): raise serializers.ValidationError('名字中不能有g') return value # 全局鉤子 # 方法就是validate(self,全部的校驗數據) # 校驗規則:成功直接返回attrs,失敗跑出校驗失敗信息 def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise serializers.ValidationError({'re_password':'兩次密碼不一致'}) return attrs # 在視圖類中調用序列化類的save方法完成入庫,Serializer類能作的增入庫走create方法,改入庫走update方法 # 但Serializer沒有提供兩個方法的實現體 本身寫 def create(self, validated_data): return models.User.objects.create(**validated_data) #instance要被修改的對象,validated_data表明校驗後用來蓋instance的數據 def update(self, instance, validated_data): #用戶名不能被修改 validated_data.pop('usernamae') models.User.objects.filter(pk=instance.id).update(**validated_data) return instance
class UserV3APIView(APIView): # 單查羣查 def get(self,request,*args,**kwargs): pk=kwargs.get('pk') if pk: user_obj=models.User.objects.filter(is_delete=False,pk=pk).first() if not user_obj: return Response({ 'status':1, 'msg':'pk error', },status=400) user_ser=serializers.UserModelSerializer(user_obj,many=False)#將從數據庫查到的數據對象傳進去,many默認爲False,單查,返回的也是一個類實例化的對象 return Response({ 'status':0, 'msg':'ok', 'results':user_ser.data }) else: #將對象對外提供的字段,已經整個序列化過程封裝,造成序列化類 user_query=models.User.objects.filter(is_delete=False).all() user_ser=serializers.UserModelSerializer(user_query,many=True)#將從數據庫查到的query對象傳進去,many爲True,羣查,返回的也是一個類實例化的對象 return Response({ 'status': 0, 'msg': 'ok', 'results': user_ser.data }) # 單增 def post(self,request,*args,**kwargs): user_ser=serializers.UserModelSerializer(data=request.data) if user_ser.is_valid(): #入庫 user_obj=user_ser.save() return Response({ 'status':0, 'msg':'ok', 'results':serializers.UserModelSerializer(user_obj).data#將入庫獲得的user對象從新序列化的數據返回給前臺 }) else: return Response({ 'status': 1, 'msg': user_ser.errors, })
ModelSerializer類序列化與反序列化總結
一、序列化類繼承ModelSerializer,因此須要在配置類Meta中進行配置
二、model配置:綁定序列化相關的Model表
三、fields配置:採用 插拔式 設置全部參與序列化與反序列化字段
四、extra_kwargs配置:
劃分系統字段爲三種:只讀(read_only)、只寫(write_only)、可讀可寫(不設置)
字段是否必須:required
選填字段:在extra_kwargs進行配置,但不設置required,且有默認值
五、自定義序列化字段:
第一種(不提倡):在序列化類中用SerializerMethodField()來實現
第二種(提倡):在模型類中用@property來實現,可插拔
六、自定義反序列化字段:
同Serializer類,且規則只能在此聲明中設置,或是在鉤子中設置,在extra_kwargs中對其設置的無效
自定義反序列化字段與系統字段,設置規則同樣,因此必須設置 write_only
七、局部鉤子,全局鉤子同Serializer類
八、不須要重寫create和update方法post
class UserModelSerializer(serializers.ModelSerializer): #第一種自定義序列化字段,該字段必須在fileds中設置 #第二種:在models.py中定義 # gender=serializers.SerializerMethodField() # def get_gender(self,obj): # return obj.get_sex_display() #自定義反序列化字段同Serializers類,且規則只能在此聲明中設置,或是在鉤子中設置 #在extra_kwargs中對其設置的無效 #注:自定義反序列化字段與系統字段,設置規則同樣,全部必須設置write_only re_password=serializers.CharField(min_length=3,max_length=16,write_only=True) class Meta: model=models.User #fileds採用插拔式 設置全部參與序列化字段 fields=('usernamae','gender','icon','password','sex','re_password') extra_kwargs={ 'usernamae':{#系統字段不設置read_only和write_only,默認都參加 'min_length':3, 'max_length':10, 'error_messages':{ 'min_length': '過短', 'max_length': '太長' } }, 'gender':{ 'read_only':True,#自定義的序列化字段默認就是read_only,且不能修改,能夠忽略 }, 'password':{ 'write_only':True, }, 'sex':{ #像sex有默認值的字段,爲選填字段(‘required’:True能夠將其變爲必填字段 'write_only':True # 'required':True } } # 局部全局鉤子同Serializer類,是與 Meta 同縮進的 def validate_username(self, value): if 'g' in value.lower(): raise serializers.ValidationError('名字中不能有g') return value def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise serializers.ValidationError({'re_password': '兩次密碼不一致'}) return attrs # create和update方法不須要再重寫,ModelSerializer類已提供,且支持全部關係下的連表操做
from django.db import models # Create your models here. class User(models.Model): SEX_CHOICES=( (0,'女'), (1,'男') ) usernamae=models.CharField(max_length=64,verbose_name='用戶名',blank=True,unique=True) password=models.CharField(max_length=64,verbose_name='密碼') sex=models.IntegerField(choices=SEX_CHOICES,default=0,verbose_name='性別') img=models.ImageField(upload_to='img',default='img/default.png',verbose_name='頭像') #開發中,數據不會直接刪除,用過字段控制 is_delete=models.BooleanField(default=False,verbose_name='是否註銷') #數據庫數據入庫,通常都會記錄該數據第一次入庫時間,有時候還會記錄最後一次更新時間 create_time=models.DateTimeField(auto_now_add=True,verbose_name='建立時間') #第二種自定義序列化字段(插拔式,提倡使用) @property def gender(self): return self.get_sex_display() @property def icon(self): from django.conf import settings return '%s%s%s' % (settings.BASE_URL, settings.MEDIA_URL, self.img) class Meta:#配置類,給你所屬類提供配置信息 db_table='old_boy_user' verbose_name_plural='用戶表' def __str__(self):#不要在這裏進行連表操做,admin頁面可能會崩潰 return self.usernamae
"""