DRF使用扩展

序列化器

1.drf序列化器校验时获取字段数据

is_valid之前: self.initial_data.get('')

is_valid之后:self.validate_data.get('')

 

2.序列化器选项

field= "__all__"

exclude=['user','name']

list和create 的字段差距较大时,可以创建两个序列化器

  • 查询大多时候需要序列化所有字段

  • 创建只需要传入规定字段,若是使用查询序列化器,其他字段传入了,也会被写入,比如:

    • 评论数: 一条朋友圈刚创建时,值应该为0,若前端传来一个 conment=100,那就直接评论数写为100了

以上当然也可以设置字段只读或只写来实现

一个视图使用不同的序列化器

重写get_serializer_class():

def get_serializer_class(self):
    """
    Return the class to use for the serializer.
    Defaults to return `self.serializer_class`.
    """
    if self.request.method == 'GET':
        return self.serializer_class
    elif self.request.method == 'POST':
        return CreateNewsSerializer

3.嵌套序列化

有一些字段,前端传过来时是以列表形式或列表套字典形式,这种序列化器无法直接序列化:

需使用嵌套的序列化:

# 前端传值形式:
{
    title:'xxx'
    content:'xxxxx'
    imageList:[
        {
            key:'xxxx',
            cos_path:'xxxx'
        },{
        key:'xxxx',
        cos_path:'xxxx'
        }],
}
​
class CreateImageModelSerializer(serializers,ModelSerializer):
    key = serializers.CharField()
    cos_path = serializer.charFiled()
​
class CreateNewsModelSerializer(serializers,ModelSerializer):
    # 添加额外校验字段
    imageList = CreateImageModelSerializer(many=True)

创建记录时,使用ModelViewSet中的CreateModelMixin:

def perform_create(self, serializer):
serializer.save(user_id=1)  // 添加一个字段用于创建记录

4.使用方法改变字段序列化的值

正常序列化结果:
{   
    title:‘xxx’,
    content:'xxx',
    user:1,
    topic:1,
}
​
使用serializerMethodField改变字段取值:
class NewsSerializer(serializers.ModelSerializer):
   user = serializer.serializerMethodField()
   topic = serializer.serializerMethodField()
   
   def get_user(self,obj):
        # retturn {'name':'obj.user.name',avatar:'obj.user.avatar'}
        retturn model_to_dict(obj.user,fields=[name,avatar]) # 还可以使用参数exclude
   def get_topic(self,obj):
        ......

5.在serializer中获取 request 请求对象

# 通过视图对象self 的 context属性:
self.context['request']

 

认证组件

一个视图根据不同请求方法,使用不同认证组件

  1. 重写get_authenticators()方法 :

如果碰到一个视图类,包含 增删改查 多个方法接口,比如:get,post,不同的方法需要不同的认证类,那么在类中定义的authentication_class 类属性就无法兼容各个接口;

比如:评论的列表页和发布页,分别对应getpost两个接口,列表页无需登录认证,发布页需要认证;可以通过 重写get_authenticators()方法实现:

class CommentView(APIView):
# authentication_class = [ListAuth,CreateAuth]  
   
   def get_authenticators(self):
       if self.request.method == 'POST':
           return [ListAuth(),]
       return [CreateAuth(),]
   
def get(self,request,*args, **kwargs):
pass
def post(self, request, *args, **kwargs):
pass
  1. 好像也可以使用 authentication的装饰器 来装饰请求方法

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/Deaseyy/p/13642969.html