【问题标题】:Dynamically include or exclude Serializer class fields动态包含或排除 Serializer 类字段
【发布时间】:2013-09-15 13:07:06
【问题描述】:

在我的 User 配置文件模型中,我明确包含了一个 show_email 字段。因此,要将此功能添加到我的 API,UserSerializer 类如下所示:

class UserSerializer(serializers.ModelSerializer):
    email = serializers.SerializerMethodField('show_email')

    def show_email(self, user):
        return user.email if user.show_email else None

    class Meta:
        model = django.contrib.auth.get_user_model()
        fields = ("username", "first_name", "last_name", "email")

但我真的不喜欢它。我认为如果将字段email 完全排除在序列化程序输出中,它会更干净,show_emailFalse,而不是显示丑陋的"email": null 东西。

我该怎么做?

【问题讨论】:

标签: django django-rest-framework


【解决方案1】:

您可以在 API 视图中通过覆盖返回响应的方法(即 API 视图的“动词”)来执行此操作。例如,在 ListAPIView 中,您将覆盖 get()

class UserList(generics.ListAPIView):
    model = django.contrib.auth.get_user_model()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        response = super(UserList, self).get(request, *args, **kwargs)
        for result in response.data['results']:
            if result['email'] is None:
                result.pop('email')
        return response

您可能希望添加更多属性检查,但这就是如何完成的要点。此外,我还要补充一点,如果从某些结果中删除字段可能会导致消费应用程序出现问题,如果它希望它们出现在所有记录中。

【讨论】:

    【解决方案2】:

    这个答案来晚了,但对于未来的谷歌搜索:文档中有一个关于 Dynamically modifying fields 的示例。 因此,通过将参数传递给序列化程序,您可以控制是否处理字段:

    serializer = MyPostSerializer(posts, show_email=permissions)
    

    然后在序列化程序的 init 函数中,您可以执行以下操作:

    class MyPostSerializer(serializers.ModelSerializer):
    
    def __init__(self, *args, **kwargs):
        show_email = kwargs.pop('show_email', None)
    
        # Instantiate the superclass normally
        super(DeviceSerializer, self).__init__(*args, **kwargs)
    
        if not show_email:
            self.fields.pop("show_email")
    

    现在 show_email 字段将被序列化程序忽略。

    【讨论】:

    • 试一试,它不起作用。这适用于实例的字段(模型字段)enail 是一个定义的额外字段,您需要将其删除为 m ._data,因为这不是一个有效的选择(顾名思义)。
    【解决方案3】:

    您可以在序列化程序上覆盖 restore_fields 方法。在 restore_fields 方法中,您可以修改字段列表 - serializer.fields - 弹出、推送或修改任何字段。

    例如:当操作不是“创建”时,字段工作区是只读的

    class MyPostSerializer(ModelSerializer):
    
    def restore_fields(self, data, files):
        if (self.context.get('view').action != 'create'):
            self.fields.get('workspace').read_only=True
        return super(MyPostSerializer, self).restore_fields(data, files)
    
    class Meta:
        model = MyPost
        fields = ('id', 'name', 'workspace')
    

    【讨论】:

    • 这似乎是过时的答案。在版本 3.2.1 中至少没有方法restore_fields。可能现在更好的方法是使用在视图/集的 get_serializer 中应用的单独的序列化器。对于这个单独的序列化程序,如果需要某些东西,则使用继承并在 Meta 中通过 extra_kwargs 进行修改。
    【解决方案4】:

    这可能会有所帮助... 要在 API 请求中动态包含或排除字段,修改 @stackedUser 在下面的响应应该这样做:

      class AirtimePurchaseSerializer(serializers.Serializer):
    
          def __init__(self, *args, **kwargs):
            try:
                phone = kwargs['data']['res_phone_number']
            except KeyError:
                phone = None
    
            # Instantiate the superclass normally
            super(AirtimePurchaseSerializer, self).__init__(*args, **kwargs)
    
            if not phone:
                self.fields.pop("res_phone_number")
    
         res_phone_number = serializers.CharField(max_length=16, allow_null=False)
    

    【讨论】:

      猜你喜欢
      • 2015-03-12
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 2011-11-24
      • 2017-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多