动态字段
用途:
- 大多数django返回list数据的时候性能瓶颈都在序列化,可以通过削减序列化字段,以只满足接口需要为标准来定制序列化器.但是每次增加一个新序列化器都要抽象基类会增加开发工作,增加代码复杂度,降低可读性.这里提供另一个思路,首先做出一个大而全的序列化器,然后按照<需要的字段>参数来做缩减.
- 除了上面的性能原因,还有一些时候我们会需要根据用户字段权限来限制返回的内容,此时也可以使用此序列化器基类
类
drf默认的ModelSerializer是不支持动态修改字段的.但是可以通过自定义的方法来实现
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional fields argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
使用方法
假如有一个地方是给让用户指派负责人的.需要给前端一个只要username和id的列表,定义为新的 options 接口.
继承基类
class UserSerializer(DynamicFieldsModelSerializerserializers.ModelSerializer):
mixture_name = serializers.SerializerMethodField(read_only=True)
department_name = serializers.StringRelatedField(source='department.name')
def get_mixture_name(self, obj):
"""
返回包含拼音和中文的名称,用以区分中文相同的用户
中文(英文)
"""
if obj == None:
return ""
return "{}({})".format(obj.nickname, obj.username)
class Meta:
model = User
fields = ('id', 'username', 'nickname', 'mixture_name', 'department_name')
重写viewset中的get_serializer方法
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
# 在调用action接口时,传入fields参数,值为想要的2个字段名.
if self.action == 'options':
kwargs['fields'] = ('id','usernanme')
return serializer_class(*args, **kwargs)
options接口
@action(methods=['GET'], detail=False)
def options(self, request, *args, **kwargs):
return super(UserViewSet, self).list(request, *args, **kwargs)