Django REST Framework笔记(六)重写序列化器的update和create方法

序列化器中update、create和视图中的update、create

在序列化器中和视图中,都可以重写updatecreate方法,但两者有什么区别呢?

说实话,我还未搞懂,看不懂源码。这里我可以拿笔记中的案例来分析分析。

本笔记中有以下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那可是很麻烦的。

好了,以后若有新的领悟,再来更新。

接下来要学习认证了。

你可能感兴趣的:(DRF学习笔记)