Camille Tolsa
Camille Tolsa

Reputation: 261

Python Django rest-framework serializer omitting field

I'm facing a problem using python2.7 with django rest-framework. When I serialize my JSON data, a field is omitted by the serializer and I don't understand why. Here is some details.

The missing field is "country". When I'm doing POST or PUT requests on /campaigns/:id

class CampaignSerializer(serializers.HyperlinkedModelSerializer):
    created_by = UserFullSerializer(read_only=True)
    country = CountrySerializer(read_only=True)

    class Meta:
        model = Campaign
        fields = ('id', 'created_by', 'name', 'media', 'status', 'begin', 'end', 'country')


class CampaignFullSerializer(serializers.HyperlinkedModelSerializer):
    client = ClientSerializer(read_only=True)
    collection = CollectionSerializer(read_only=True)
    created_by = UserFullSerializer(read_only=True)
    updated_by = UserFullSerializer(read_only=True)
    channels = ChannelSerializer(read_only=True, many=True)
    country = CountrySerializer(read_only=True)

    class Meta:
        model = Campaign
        fields = ('id',
                  'client',
                  'name',
                  'media',
                  'status',
                  'begin',
                  'end',
                  'created_at',
                  'created_by',
                  'updated_at',
                  'updated_by',
                  'collection',
                  'channels',
                  'country')

class CountrySerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Country
        fields = ('id', 'name', 'code')


class Country(models.Model):
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255)

class Campaign(models.Model):
    name = models.CharField(max_length=255)
    media = models.IntegerField(choices=constant.MEDIA_CHOICES, default=0)
    status = models.IntegerField(choices=constant.STATUS_CHOICES, default=2)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(User, blank=True, null=True, related_name="created_by")
    updated_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    updated_by = models.ForeignKey(User, blank=True, null=True, related_name="updated_by")
    client = models.ForeignKey(client.Client)
    begin = models.DateField(blank=True, null=True)
    end = models.DateField(blank=True, null=True)
    collection = models.ForeignKey(collection.Collection, blank=True, null=True)
    country = models.ForeignKey(country.Country, blank=True, null=True)
    mediaplan = models.ForeignKey(mediaplan.Mediaplan, blank=True, null=True, default=None)
    channels = models.ManyToManyField(channel.Channel)

When I'm doing POST on /campaign/id with the following JSON, everything works except the country field.

{
    ...
    "channels": [],
    "country": {
        "id": 74,
        "name": "France",
        "code": "FR"
}

On the controller side when I print the request.data I got all the fields. I'm not overriding the create method of the controller.

{
    ...
    u'country': {u'code': u'AL', u'id': 3, u'name': u'Albania'}
}

My controller looks like:

class CampaignViewSet(viewsets.ModelViewSet):
    queryset = Campaign.objects.all()
    serializer_class = CampaignSerializer

    def create(self, request):
        logger.info(request.data)
        return super(CampaignViewSet, self).create(request, *args, **kwargs)

I tried to override the create method of my CountrySerializer and when I print the content of validated_data, the country field is missing in the OrderedDict..

class CountrySerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Country
        fields = ('id', 'name', 'code')

        def create(self, validated_data):
            logger.info(validated_data)

I'm really lost, I can't find my mistake, maybe you will. Thanks for your time.

Upvotes: 0

Views: 2344

Answers (1)

Ben Hare
Ben Hare

Reputation: 4415

Your CountrySerializer is read only as a nested serializer by default (per http://www.django-rest-framework.org/api-guide/relations/#nested-relationships) so you have to override the create/update method of the Campaign serializer for POST/PUT. You've tried to override it on the Country serializer instead.

Upvotes: 1

Related Questions