8

I would like to have a nested object inside a serializer instead of just the foreignkey (or url). As this documentation says, I just had to specify the serializer class of the nested object in the parent serializer:

# 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

This works very well when I get the objects, but it is not possible to create (=POST) Sample objects anymore, I get the error:

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

I tried to overwrite the create method in the viewset to get the object using the pk:

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)

But it doesn't work as well.

Any idea?

I also found this question I can relate with which of course solves the problem but do not let me expose the full nested object, so back to the beginning.

Thanks,

2
  • You shouldn't need that overridden create to populate your request data with a NestedSample instance, the PK string should work by itself. Commented May 21, 2014 at 0:23
  • See this answer: stackoverflow.com/questions/23686888/… Commented May 22, 2014 at 10:04

2 Answers 2

3

Can you confirm that you're sending a JSON encoded request - i.e. the request has the content type set to JSON ? If not, the post is most probably send using form format which doesn't support nested.

Sign up to request clarification or add additional context in comments.

3 Comments

No, I just send the values using the basic format, I don't know its name: ?thing=1&nested=2 and I send the pk of an existing nested object, I don't want to create a new one.
Using the rest_framework.test.APIClient in my tests fixed this for me. (django-rest-framework.org/api-guide/testing#apiclient)
This is the first mention that I found of getting the encoding correct at test time - thanks @XavierOrdoquy ... Adding format='json' to my client.post request at test time fixed this for me.
2

I can think of two solutions to this problem. I prefer the first one.

First solution:

Use a django model form to create objects. Override the create and update methods. A sample create method:

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)

this way you can create Sample objects with any kind of validation you like.

Second solution:

Override get_serializer_class method and return serializer class based on request method. Define two serializers one for post and put and one for list and retrieve.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.