05-Django REST framwork 板塊(06-序列化)

6. 序列化

兩大功能:
1. 對請求數據的驗證
2. 對querset進行序列化

一.序列化:

利用ser.data獲得經過序列化得到的數據,ser爲經過數據庫查詢得到的query對象(ret = models.Role.objects.all())

1.寫類

兩種基本寫法:from rest_framework.serializers import ...

一種繼承自Serializer,
第二種繼承自ModelSerializer,自動數據庫表裏邊,自動生成Serializer的字段

class RolesSerializer(serializers.Serializer):
	id = serializers.IntegerField()
	title = serializers.CharField()

class UserInfoSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		# fields = "__all__"  # 可以自動生成所有字段,但是默認拿的都是最基本的
		fields = ['id','username','password',]  # 寫數據庫的字段
2.字段

a.

title = serializers.CharField(source="xxx.xxx.xx.xx")
重點:獲取choice字段顯示
  1. source爲對應數據庫的字段名稱,這樣前邊的title就可以隨便定義了

  2. source針對如含choice等字段,可以執行get_字段名_display 方法 進行顯示,如source='get_usertype_display'

  3. source針對外鍵等情況,可以使用 xx.屬性名,進行調用,如:source='group.id'

  4. 當要查的不只是一個數據,可以用SerializerMethodField進行自定義顯示,可以定義一個
    get_ 開頭的方法/函數,函數返回什麼,就顯示什麼(如下:get_rls

b.


  title = serializers.SerializerMethodField()
  class UserInfoSerializer(serializers.ModelSerializer):
	rls = serializers.SerializerMethodField()  # 自定義顯示
	haha = serializers.CharField(source='get_usertype_display')
	class Meta:
		model = models.UserInfo
		# fields = "__all__"  # 可以自動生成多有字段,但是默認拿的都是最基本的
		# 可以跟自定義的字段,混合着中。對於額外數據也可以depth進行深度提取,拿到更多數據
		# 對於有格外操作的,可以定義上邊單獨字段,然後添加到files中
		fields = ['id','username','password','rls','haha'] 
	 
	# 自定義方法
	def get_rls(self, row):
		role_obj_list = row.roles.all()

		ret = []
		for item in role_obj_list:
			ret.append({'id':item.id,'title':item.title})
		return ret

c. 自定義類

  • 可以繼承CharFiled等字段,進行自己的再封裝。用的不多
3. 自動序列化連表、深度depth
class UserInfoSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.UserInfo
		# fields = "__all__"
		fields = ['id','username','password','group','roles']  #可對應添加含字段的字段名稱
		depth = 1 # 官方建議0 ~ 10(取數據的深度,如果只拿到數據ID,可以再往深的取對應的描述文字)
		# 層數越深,數據越多,檢索越多,影響性能,平時到3已經很大了  
4. 生成鏈接(反向解析)

url(r'^(?P<version>[v1|v2])/group/(?P<xxx>\d+)$',views.GroupView.as_view(),name='gp')

class UserInfoSerializer(serializers.ModelSerializer):
	group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='xxx')
		# view_name   >>   url處的別名
		# lookup_field  >>  url中的xxx匹配的內容,針對數據庫中所要查詢字段的索引值
		# lookup_url_kwarg  >>  取url中正則匹配的名字
	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()

		ser = UserInfoSerializer(instance=users,many=True,context={'request': request})
		ret = json.dumps(ser.data, ensure_ascii=False)
		return HttpResponse(ret)
		

源碼:

對象, Serializer類處理;
QuerySet,ListSerializer類處理;
# serializer.data

2.請求數據校驗:

對request請求過來的數據進行驗證,比如不允許傳空值,然後根據校驗規則進行相應。如:發{"pwd":""},經過驗證返回{"pwd":["標題不能爲空"]}


class XXValidator(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)

	def set_context(self, serializer_field):
		"""
		This hook is called by the serializer instance,
		prior to the validation call being made.
		"""
		# 執行驗證之前調用,serializer_fields是當前字段對象
		pass

class UserGroupSerializer(serializers.Serializer):
    # 基於title這個字段名進行,驗證;
    # 就是說請求數據,必須需包含'title',並且不能爲空
	title = serializers.CharField(error_messages={'required':'標題不能爲空'},validators=[XXValidator('老男人'),])
		# error_messages={'required':'標題不能爲空'}  #自定義出錯的信息
		# validators=[XXValidator('老男人'),]  #自定義驗證規則(上邊的XXValidator)
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('提交數據')
		

問: 自定義驗證規則時,需要鉤子函數?請問鉤子函數如何寫?

答:從is_vaild()方法開始找源碼,注意self要先從自己定義的類進行查找,然後在一步步深入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章