DRF中通过请求方式不同使用不同的序列化器

models.py  模型类

from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    phone = models.CharField(max_length=32,unique=True)  # 唯一
    icon = models.ImageField(upload_to='icon',default='icon/default.png')
    # 需要配置media文件夹 上传文件会默认放到media/icon文件夹下

gerneral_ser.py  序列化器

from api import models
from rest_framework import serializers
from rest_framework.validators import ValidationError

# 当注册时用UserModelSerializer序列化器
class UserModelSerializer(serializers.ModelSerializer):
    # re_password这个字段必须设置write_only 因为模型类中没有该字段
    re_password = serializers.CharField(max_length=16,required=True,write_only=True)
    class Meta:
        model = models.User
        fields = ['username','password','re_password','phone','icon']
        extra_kwargs = {
            'password':{'write_only':True},

        }

    # 局部钩子 校验手机号是否合法
    def validate_phone(self,data):
        if len(data) == 11:
            return data
        else:
            raise ValidationError('手机号必须是11位')

    # 局部钩子 校验用户名是否存在
    def validated_username(self,data):
        user_obj = models.User.objects.filter(username=data)
        if user_obj:
            raise ValidationError('用户名已经存在')
        else:
            return data

    # 全局钩子 校验两次密码是否相同
    def validate(self, attrs):
        if attrs.get('password') == attrs.get('re_password'):
            # 直接在这里将确认密码删除 后续可以直接将数据存入数据库
            attrs.pop('re_password')
            return attrs
        else:
            raise ValidationError('两次密码不一致')

    def create(self, validated_data):
        # models.User.objects.create(**validated_data)  # 保存的密码是明文的 不行
        # 如果上面的全局钩子没有删除确认密码 在这里删除也可以
        # validated_data.pop('re_password')
        user_obj = models.User.objects.create_user(**validated_data)
        return user_obj

 # 当查询单个时用UserReadOnlySerializer序列化器
class UserReadOnlySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['username','icon']

# 当修改时用UserUpdateSerializer序列化器
class UserUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['icon']

views.py视图

from api import models,ser
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,UpdateModelMixin

class RegisterView(GenericViewSet,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin):
    queryset = models.User.objects.all()
    # serializer_class = ser.UserModelSerializer

    # 通过请求方式不同使用不同的序列化器
    # 重写get_serializer_class(self)方法
    # 通过action参数来判断用哪个序列化器
    def get_serializer_class(self):
        if self.action == 'create':
            print('我是注册')
            return ser.UserModelSerializer
        elif self.action == 'retrieve':
            print('我是查询')
            return ser.UserReadOnlySerializer
        elif self.action == 'update':
            print('我是修改')
            return ser.UserUpdateSerializer

修改时通过postman对http://127.0.0.1:8000/api/register/2/发起put请求

通过选择form-data格式,key传入icon,选择files,value选择图片,即可修改头像

urls.py 路由

from django.urls import path,re_path
from api import views
from rest_framework import routers

router = routers.SimpleRouter()
router.register('register',views.RegisterView)
urlpatterns = []
urlpatterns += router.urls

总结:

我们可以通过重写get_serializer_class(self)方法,来控制不同的请求方式使用不同的序列化器

这里我们继承的是Viewset视图集,可以通过action参数来判断

如果我们继承的是APIView或者GenericAPIView,可以通过request.method来判断

posted @ 2022-05-23 21:00  _yessir  阅读(214)  评论(0编辑  收藏  举报