动态字段
用途:
- 大多数django返回list数据的时候性能瓶颈都在序列化,可以通过削减序列化字段,以只满足接口需要为标准来定制序列化器.但是每次增加一个新序列化器都要抽象基类会增加开发工作,增加代码复杂度,降低可读性.这里提供另一个思路,首先做出一个大而全的序列化器,然后按照<需要的字段>参数来做缩减.
- 除了上面的性能原因,还有一些时候我们会需要根据用户字段权限来限制返回的内容,此时也可以使用此序列化器基类
类
drf默认的ModelSerializer是不支持动态修改字段的.但是可以通过自定义的方法来实现
class DynamicFieldsModelSerializer(serializers.ModelSerializer):"""A ModelSerializer that takes an additional fields argument thatcontrols which fields should be displayed."""def __init__(self, *args, **kwargs):# Don't pass the 'fields' arg up to the superclassfields = kwargs.pop('fields', None)# Instantiate the superclass normallysuper(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 = Userfields = ('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 anddeserializing 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)
