Django-rest-framework,序列化器中的嵌套对象

8
我希望在序列化器中有一个嵌套的对象,而不仅仅是外键(或url)。 如此文档所述,我只需在父序列化器中指定嵌套对象的序列化器类即可。
# Models

class NestedSample(models.Model):
    something = models.CharField(max_length=255)

class Sample(models.Model):
    thing = models.BooleanField()
    nested = models.ForeignKey(NestedSample)

# Serializers

class NestedSampleSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = api_models.NestedSample

class SampleSerializer(serializers.HyperlinkedModelSerializer):
    nested = NestedSampleSerializer() # HERE!

    class Meta:
        model = api_models.Sample

# Views

class NestedSampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.NestedSample.objects.all()
    serializer_class = api_serializers.NestedSampleSerializer

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer

当我获取对象时,这个方法非常好用,但是不能再创建(通过POSTSample对象了,我会得到以下错误:

{u'non_field_errors': [u'Invalid data']}

我尝试覆盖视图集中的create方法以通过主键获取对象:

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer

    def create(self, request):
        request.DATA['nested'] = get_object_or_404(api_models.NestedSample, pk=request.DATA['nested'])
        return super(SampleViewSet, self).create(request)

但它并不起作用。

有什么想法吗?

我还发现了这个问题,我可以与之联系,当然解决了问题,但不允许我暴露完整的嵌套对象,所以回到开始。

谢谢。


你不需要覆盖重写 create 方法来使用 NestedSample 实例来填充请求数据,PK 字符串本身就可以工作。 - Fiver
请参考此答案:http://stackoverflow.com/questions/23686888/how-to-implement-nested-models-routes/23696134#23696134 - YAtOff
2个回答

2
我可以想到两种解决这个问题的方法,我更喜欢第一种。
第一种解决方案:
使用Django的模型表单来创建对象,重写create和update方法。以下是一个示例create方法:
def create(self, request):
    form = SampleForm(data=request.POST)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.save()
        return Response(dict(id=instance.pk), status=status.HTTP_201_CREATED)
    return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

这样,您可以创建具有任何类型验证的示例对象。
第二种解决方案:
重写get_serializer_class方法,并根据请求方法返回序列化器类。定义两个序列化器,一个用于post和put,另一个用于list和retrieve。

2

请确认您正在发送一个JSON编码的请求 - 即请求的内容类型设置为JSON?如果没有,那么这个帖子很可能是使用表单格式发送的,不支持嵌套。


不,我只是使用基本格式发送值,我不知道它的名称:?thing=1&nested=2,并且我发送现有嵌套对象的 pk,我不想创建新的对象。 - db0
在我的测试中,使用rest_framework.test.APIClient解决了这个问题。(http://www.django-rest-framework.org/api-guide/testing#apiclient) - yndolok
这是我发现在测试时间正确获取编码的第一篇提及 - 感谢 @XavierOrdoquy ... 在我的测试请求中添加 format='json' 解决了这个问题。 - jamesc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接