Django Rest Framework --序列化、请求数据校验
序列化
基本代码结构
modles.py
1 from django.db import models 2 # Create your models here. 3 4 # Create your models here. 5 class UserGroup(models.Model): 6 title=models.CharField(max_length=32) 7 8 class UserInfo(models.Model): 9 user_type_choices=((1,'普通用户'), 10 (2,"VIP"), 11 (3,"SVIP")) 12 user_type=models.IntegerField(choices=user_type_choices) 13 group= models.ForeignKey('UserGroup',on_delete=models.CASCADE,null=True) 14 roles=models.ManyToManyField('Role') 15 username=models.CharField(max_length=32,unique=True) 16 password=models.CharField(max_length=32) 17 18 class UserToken(models.Model): 19 user=models.OneToOneField(to='UserInfo',on_delete=models.CASCADE) 20 token=models.CharField(max_length=64) 21 22 class Role(models.Model): 23 title=models.CharField(max_length=32)
urls.py
from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ]
views.py
class UserinfoSerializer(ModelSerializer): # user_type = serializers.CharField(source='get_user_type_display') # role = serializers.SerializerMethodField()
#生成url group=serializers.HyperlinkedIdentityField(view_name='gu',lookup_url_kwarg='xxx',lookup_field='group_id') class Meta: model=models.UserInfo fields='__all__' # fields=['id','username','user_type','role'] depth=1 # def get_role(self, row): # roles=row.roles.all() # dict=[] # for item in roles: # dict.append({'ID':item.id,"title":item.title}) # return dict class TestView(APIView): def get(self,request,*args,**kwargs): #方法一 # roles=models.Role.objects.all().values('id','title') # roles=list(roles) # ret=json.dumps(roles,ensure_ascii=False) #方法二 # roles=models.Role.objects.all() # ser=RoleSerializer(instance=roles,many=True) # ret = json.dumps(ser.data, ensure_ascii=False) uesr=models.UserInfo.objects.all()
#生成url时,必须添加context参数 ser=UserinfoSerializer(instance=uesr,many=True,context={'request': request}) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
源码分析
1.实例化Serializer对象时,many参数的作用?
我们从实例化入手,大家知道在实例化时,首先执行的是__new__方法,然后返回对应的对象实例,所以我们一步步深入,在BaseSerializer类中找到了__new__方法。
根据判断many参数的值,来确定我们需要返回的对象实例。
2.Serializer对象是如何序列化数据的?
从data方法入手,进入data方法,返回self._data,接着我们从最外层寻找to_repersertation方法。
3.如何反向生成url?
字段类型(HyperlinkedIdentityField)就是字段生成url,在上图中,进行第一次to_represention方法是返回的是一个对象。
在HyperlinkedIdentityField类的to_represention最后调用的是django内置的生成url的方法reverse。
请求数据校验
urls.py
from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ]
views.py
class PasswordValidator(object): def __init__(self, base): self.base = base def __call__(self, value): if value != self.base: message = 'This field must be %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 UserSerializer(serializers.Serializer): ut_title = serializers.CharField(source='ut.title') user = serializers.CharField(min_length=6) pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')]) def validate_user (self,value): print(value) raise exceptions.ValidationError('拒绝你了!!!!') class TestView(APIView): def post(self, request, *args, **kwargs): # 验证,对请求发来的数据进行验证 ser = UserSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('POST请求,响应内容')
源码分析
1.实例化过程
将data赋值给initial_data
2.如果实现数据校验?
ser.is_valid()方法的返回值肯定是个bool值,进一步进入内部,看如何实现校验。