【问题标题】:Django Rest Framework return nested object using PrimaryKeyRelatedFieldDjango Rest Framework 使用 PrimaryKeyRelatedField 返回嵌套对象
【发布时间】:2013-11-24 21:16:43
【问题描述】:

我正在使用 DRF 公开一些 API 端点。

# models.py

class Project(models.Model):
    ...
    assigned_to = models.ManyToManyField(
        User, default=None, blank=True, null=True
    )



# serializers.py

class ProjectSerializer(serializers.ModelSerializer):
    assigned_to = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(), required=False, many=True)

    class Meta:
        model = Project
        fields = ('id', 'title', 'created_by', 'assigned_to')


# view.py

class ProjectList(generics.ListCreateAPIView):
    mode   = Project
    serializer_class = ProjectSerializer
    filter_fields = ('title',)

    def post(self, request, format=None):
        # get a list of user.id of assigned_to users
        assigned_to = [x.get('id') for x in request.DATA.get('assigned_to')]
        # create a new project serilaizer
        serializer = ProjectSerializer(data={
            "title": request.DATA.get('title'),
            "created_by": request.user.pk,
            "assigned_to": assigned_to,
        })
        if serializer.is_valid():
            serializer.save()
        else:
            return Response(serializer.errors,
                        status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

这一切都很好,我可以发布分配给字段的 id 列表。然而,为了实现这个功能,我必须使用PrimaryKeyRelatedField 而不是RelatedField。这意味着当我执行GET 时,我只会在assigned_to 字段中收到用户的主键。有什么方法可以保持POST 的当前行为,但返回assigned_to 字段的序列化User 详细信息?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    我最近使用子类 PrimaryKeyRelatedField() 解决了这个问题,它使用 id 作为输入来设置值,但使用序列化程序返回嵌套值。现在这可能不是这里要求的 100%。 POST、PUT 和 PATCH 响应也将包括嵌套表示,而问题确实指定 POST 的行为与 PrimaryKeyRelatedField 的行为完全相同。

    https://gist.github.com/jmichalicek/f841110a9aa6dbb6f781

    class PrimaryKeyInObjectOutRelatedField(PrimaryKeyRelatedField):
        """
        Django Rest Framework RelatedField which takes the primary key as input to allow setting relations,
        but takes an optional `output_serializer_class` parameter, which if specified, will be used to
        serialize the data in responses.
    
        Usage:
            class MyModelSerializer(serializers.ModelSerializer):
                related_model = PrimaryKeyInObjectOutRelatedField(
                    queryset=MyOtherModel.objects.all(), output_serializer_class=MyOtherModelSerializer)
    
                class Meta:
                    model = MyModel
                    fields = ('related_model', 'id', 'foo', 'bar')
    
        """
    
        def __init__(self, **kwargs):
            self._output_serializer_class = kwargs.pop('output_serializer_class', None)
            super(PrimaryKeyInObjectOutRelatedField, self).__init__(**kwargs)
    
        def use_pk_only_optimization(self):
            return not bool(self._output_serializer_class)
    
        def to_representation(self, obj):
            if self._output_serializer_class:
                data = self._output_serializer_class(obj).data
            else:
                data = super(PrimaryKeyInObjectOutRelatedField, self).to_representation(obj)
            return data
    

    【讨论】:

      【解决方案2】:

      在这种情况下,您需要为 POSTGET 使用不同的序列化程序。

      看看覆盖视图上的get_serializer_class() 方法,并根据self.request.method 切换返回的序列化程序。

      【讨论】:

      • 所以,我尝试覆盖 get_serializer_class() 方法:def get_serializer_class(self): print self.request.method; if self.request.method == "GET": ...,但请求始终为GET,即使我在运行服务器中看到POST
      猜你喜欢
      • 2017-04-09
      • 1970-01-01
      • 2017-12-29
      • 2013-07-05
      • 2019-01-13
      • 2016-01-22
      • 1970-01-01
      • 2021-12-10
      • 2015-08-26
      相关资源
      最近更新 更多