【问题标题】:Exclude fields when nesting serializer Django REST Framework嵌套序列化程序 Django REST Framework 时排除字段
【发布时间】:2020-05-12 12:43:54
【问题描述】:

序列化器.py

class ThreadSerializer(serializers.ModelSerializer):

    author = UserSerializer(read_only=True)
    last_post_user = UserSerializer(read_only=True)

    class Meta:
        model = Thread
        fields = '__all__'
        read_only_fields = ('locked', 'views', 'post_count', 'last_post_time')


class ChannelSerializer(serializers.ModelSerializer):

    threads = ThreadSerializer(many=True, read_only=True)

    class Meta:
        model = Channel
        fields = ['id', 'name', 'description', 'category', 'threads']


class CategorySerializer(serializers.ModelSerializer):

    channels = ChannelSerializer(many=True, read_only=True)

    class Meta:
        model = Category
        fields = ['id', 'name', 'channels']

您会注意到我在 CategorySerializer 中嵌套了 ChannelSerializer,当我访问使用 CategorySerializer 查询数据的端点时,我希望它会仅列出来自 ChannelSerializer 的数据,但是它也列出来自 ThreadSerializer 的数据,我认为这是预期的行为,因为 ThreadSerializer 嵌套在 em>ChannelSerializer

当我嵌套序列化程序时,是否有一些优雅的方法可以排除字段?在这种情况下,我想在使用 CategorySerializer

查询数据时排除 threads

我尝试了类似 question 的答案,但不幸的是,它似乎无法在我的情况下工作,它最终再次列出了线程,我认为还有更简单的方法可以做到这一点。

【问题讨论】:

  • Meta 选项中删除不必要的字段不是很难吗?
  • @ArakkalAbu 我可以这样做,但我有一个不同的端点,它依赖于 ChannelSerializer,我希望在其中包含线程字段。我猜想使用 Meta 选项排除该字段将全局排除该字段。
  • 然后,使用多个序列化程序(我会这样做)
  • 您可以创建另一个不包含线程字段的 ChannelSerializer 版本,并在 CategorySerializer 中引用它。
  • 正在考虑使用单独的序列化程序,但它似乎有点多余,但我想当我需要字段过滤时我会坚持使用它。谢谢:)

标签: python django django-rest-framework


【解决方案1】:

创建一个不同的序列化程序并删除您不想要的字段(请参阅this answer)是一个更好的选择,但这里有一个替代方案:

class CategorySerializer(serializers.ModelSerializer):

    channels = ChannelSerializer(many=True, read_only=True)

    # Override so we can remove unwatned fields
    def to_representation(self, instance):
        rep = super().to_representation(instance)
        del rep["channels"]["threads"]
        return rep

    ...

在这种情况下,“threads”键不会出现在 API 的响应中,但为每个通道返回线程的查询仍将运行(换句话说,它可以工作,但性能较差)。

【讨论】:

    【解决方案2】:

    我有一个使用不同序列化程序的简单 sn-p。你可以扩展它以防万一。

    Serializers.py

    class CSerializer(serializers.ModelSerializer):
    
      class Meta:
        model = C
        fields = ('id', 'f1')
    
    class BSerializer(serializers.ModelSerializer):
      c = CSerializer(many=True, read_only=True)
    
      class Meta:
        model = B
        fields = ('id', 'f1', 'c')
    
    class ASerializer(serializers.ModelSerializer):
      b = BSerializer(many=True, read_only=True)
    
      class Meta:
        model = A
        fields = ('id', 'f1', 'b')
    
    
    # --------------------------------------------------- #
    class CustomBSerializer(serializers.ModelSerializer):
    
      class Meta:
        model = B
        fields = ('id', 'f1')
    
    class CustomASerializer(serializers.ModelSerializer):
      b = CustomBSerializer(many=True, read_only=True)
    
      class Meta:
        model = A
        fields = '__all__'
    
    # --------------------------------------------------- #
    

    Views.py

    class AView(generics.ListAPIView):
      """List C objects"""
      queryset = A.objects.all()
    
      def get_serializer_class(self):
       url = self.request.path
       if url == reverse("test1"):
         return ASerializer
       elif url == reverse("test2"):
        return CustomASerializer
    

    urls.py

    urlpatterns = [
      path('test1/', AView.as_view(), name="test1"),
      path('test2/', AView.as_view(), name="test2")
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      相关资源
      最近更新 更多