我有一个在几个端点(generics.ListAPIView)中使用的序列化器,但在其中一个端点中我需要隐藏序列化器字段。我不想仅仅为了解决这种情况而编写新的序列化器。
从 DRF 3.0 开始,我们为序列化器提供了动态字段 ( https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields ),但我在完全理解如何使用它们时遇到了一些麻烦。
我创建了这个序列化器:
class TestSerializer(DynamicFieldsModelSerializer):
user_req = UserSerializer(read_only=True)
user_tar = UserSerializer(read_only=True)
class Meta:
model = TestAssoc
fields = ("user_req", "user_tar")
这是我的端点:
class TestEndpointListAPIView(generics.ListAPIView):
serializer_class = TestSerializer
permission_classes = [IsAuthenticated]
lookup_field = 'test_username'
def get_queryset(self):
return ...
现在我需要从输出中隐藏“user_tar”字段,根据文档,我应该使用以下内容实例化序列化器:
TestSerializer(fields=('user_req'))
但是我应该如何在 TestEndpointListAPIView 中执行此操作?我应该重写 get_serializer 吗?
感谢您的帮助
编辑:
我通过重写 get_serialized 函数找到了以下解决方案:
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
kwargs['fields'] = ['user_req']
return serializer_class(*args, **kwargs)
我想知道这是否是一个好的解决方案。谢谢!
最佳答案
按照 DRF docs 中的建议,将这段代码添加到序列化器类的 __init__
方法中:
class TestSerializer(serializers.ModelSerializer):
user_req = UserSerializer(read_only=True)
user_tar = UserSerializer(read_only=True)
class Meta:
model = TestAssoc
fields = ("user_req", "user_tar")
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(TestSerializer, 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)
for field_name in existing - allowed:
self.fields.pop(field_name)
因此,当您从views.py 调用序列化器时,请执行以下操作:
TestSerializer(queryset, fields=('user_req'))
或者你可以做的是定义一个类
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields is not None:
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
如果您已在其他文件中定义了该类,则现在导入该类,然后使用
继承它class TestSerializer(DynamicFieldsModelSerializer):
这样:
class TestSerializer(DynamicFieldsModelSerializer):
user_req = UserSerializer(read_only=True)
user_tar = UserSerializer(read_only=True)
class Meta:
model = TestAssoc
fields = ("user_req", "user_tar")
现在你可以做
TestSerializer(queryset, fields=('user_req'))
更新
意见中。以ListAPIView为例
class DemoView(ListAPIView):
queryset = TestAssoc.objects.all()
def get(self, request):
try:
queryset = self.get_queryset()
data = TestSerializer(queryset, fields=('user_req')).data
return Response( {"data" : data } ,status=status.HTTP_200_OK)
except Exception as error:
return Response( { "error" : str(error) } , status=status.HTTP_500_INTERNAL_SERVER_ERROR)
关于Django休息框架: using DynamicFieldsModelSerializer for excluding serializer fields,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54893891/