动态字段

用途:

  1. 大多数django返回list数据的时候性能瓶颈都在序列化,可以通过削减序列化字段,以只满足接口需要为标准来定制序列化器.但是每次增加一个新序列化器都要抽象基类会增加开发工作,增加代码复杂度,降低可读性.这里提供另一个思路,首先做出一个大而全的序列化器,然后按照<需要的字段>参数来做缩减.
  2. 除了上面的性能原因,还有一些时候我们会需要根据用户字段权限来限制返回的内容,此时也可以使用此序列化器基类

    drf默认的ModelSerializer是不支持动态修改字段的.但是可以通过自定义的方法来实现

  1. class DynamicFieldsModelSerializer(serializers.ModelSerializer):
  2. """
  3. A ModelSerializer that takes an additional fields argument that
  4. controls which fields should be displayed.
  5. """
  6. def __init__(self, *args, **kwargs):
  7. # Don't pass the 'fields' arg up to the superclass
  8. fields = kwargs.pop('fields', None)
  9. # Instantiate the superclass normally
  10. super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
  11. if fields is not None:
  12. # Drop any fields that are not specified in the `fields` argument.
  13. allowed = set(fields)
  14. existing = set(self.fields.keys())
  15. for field_name in existing - allowed:
  16. self.fields.pop(field_name)

使用方法

假如有一个地方是给让用户指派负责人的.需要给前端一个只要username和id的列表,定义为新的 options 接口.

  1. 继承基类

    1. class UserSerializer(DynamicFieldsModelSerializerserializers.ModelSerializer):
    2. mixture_name = serializers.SerializerMethodField(read_only=True)
    3. department_name = serializers.StringRelatedField(source='department.name')
    4. def get_mixture_name(self, obj):
    5. """
    6. 返回包含拼音和中文的名称,用以区分中文相同的用户
    7. 中文(英文)
    8. """
    9. if obj == None:
    10. return ""
    11. return "{}({})".format(obj.nickname, obj.username)
    12. class Meta:
    13. model = User
    14. fields = ('id', 'username', 'nickname', 'mixture_name', 'department_name')
  2. 重写viewset中的get_serializer方法

    1. def get_serializer(self, *args, **kwargs):
    2. """
    3. Return the serializer instance that should be used for validating and
    4. deserializing input, and for serializing output.
    5. """
    6. serializer_class = self.get_serializer_class()
    7. kwargs['context'] = self.get_serializer_context()
    8. # 在调用action接口时,传入fields参数,值为想要的2个字段名.
    9. if self.action == 'options':
    10. kwargs['fields'] = ('id','usernanme')
    11. return serializer_class(*args, **kwargs)
  3. options接口

    1. @action(methods=['GET'], detail=False)
    2. def options(self, request, *args, **kwargs):
    3. return super(UserViewSet, self).list(request, *args, **kwargs)