序列化器中update、create和视图中的update、create
在序列化器中和视图中,都可以重写update
和create
方法,但两者有什么区别呢?
说实话,我还未搞懂,看不懂源码。这里我可以拿笔记中的案例来分析分析。
本笔记中有以下models
from django.db import models
class Company(models.Model):
company_name = models.CharField(max_length=50)
def __str__(self):
return self.company_name
class Tag(models.Model):
tag = models.CharField(max_length=30)
def __str__(self) -> str:
return self.tag
class User(models.Model):
STATUS_CHOICE = (
('1', '有效账号'),
('2', '无效账号')
)
user_name = models.CharField(max_length=20, unique=True)
nick_name = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=20)
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING)
status = models.CharField(max_length=20, choices=STATUS_CHOICE, default=1)
tags = models.ManyToManyField(Tag)
def __str__(self) -> str:
return self.user_name
其中,password
的字段,设置成了序列化时不传送到前端,反序列化时必须要提供(其他字段没这个困扰,毕竟谁会把密码传送到前端呢?)。但是前端在修改数据时,不一定会修改password
,那么数据传到后端时要判断一下,如果前端不修改密码的话,那就使用实例原有的密码。
那么,问题来了。
如果前端不修改密码,则使用实例密码
这个步骤需要重写update
方法,要重写哪个update
呢?是序列化器中的,还是视图中的?也就是说,要在视图拿到数据判断还是数据反序列化时判断?
- 先看看序列化器中的update
def update(self, instance, validated_data):
instance.password = validated_data.get('password', instance.password)
return super().update(instance, validated_data)
这里需要注意形参validate_data
,它是一个经过drf
校验的字典,里面的数据来源于request.data
。
当前端不修改密码,request.data
中必定不包含password
的键值对,那这个request.data
没办法通过drf
的校验,那自然不会存在所谓的validate_data
。
经过实践,修改密码的这个需求不能在序列化器中重写update
实现,可以在视图中重写update
实现。代码如下:
class UserViewSets(viewsets.ModelViewSet):
queryset = User.objects.all()
def get_serializer_class(self):
serializer_class = self.serializer_class #由于封装中内置了serializer_class,所以这里必须使用self.serializer_class,否则serializer_class就变成一个新的变量了
if self.request.method in ('PUT', 'POST',):
serializer_class = UserModelPostPut
if self.request.method in ('GET', ):
serializer_class = UserModelGetSerializer
return serializer_class
def update(self, request, *args, **kwargs):
if not request.data.get('password'):
password = User.objects.get(id=request.data['id']).password
request.data['password'] = password
return super().update(request, *args, **kwargs)
return super().update(request, *args, **kwargs)
def destroy(self, request, *args, **kwargs):
super().destroy(request, *args, **kwargs)
return Response('删除')
还未尝试过create
方法,不过原理差不多,想要在序列化器中重写update
create
,必须确保request.data
能通过drf
的校验,这样才能有validate_data
。
我想,应该还有另外一个区别。
序列化器是可以重复调用的,对应的update
create
方法也一样可以重复调用。而视图可以有很多个,比如基于@api_view
实现的,基于APIView
实现的,还有其他方法实现的视图,如果每个视图都要重写一遍update
那可是很麻烦的。
好了,以后若有新的领悟,再来更新。
接下来要学习认证了。