Django Rest Framework 3.0: Saving Nested Relationship With ForeignKey

4,146 views
Skip to first unread message

Louis Lang

unread,
Dec 31, 2014, 12:14:40 AM12/31/14
to django-res...@googlegroups.com
I'm attempting to build a nested relationship using Django Rest Framework 3.0. I've created my serializers and have attempted to override the `create()` function. My models are defined as follows:

   
 class Item(models.Model):
     user
= models.ForeignKey(settings.AUTH_USER_MODEL)
     name
= models.CharField(max_length=200)
     description
= models.CharField(max_length=1000)
     categories
= models.ManyToManyField(Category, null=True, blank=True)


 
class Price(models.Model):
     user
= models.ForeignKey(settings.AUTH_USER_MODEL)
     item
= models.ForeignKey(Item, related_name='prices')
     name
= models.CharField(max_length=100)
     
cost = models.FloatField()


As you'll note, I can have multiple prices for my items. My serializers are defined as follows:

class PriceSerializer(serializers.ModelSerializer):
   
class Meta:
        model
= Price
        owner
= serializers.Field(source='owner.username')
        exclude
= ('user',)


class ItemSerializer(serializers.ModelSerializer):
    prices
= PriceSerializer(many=True, required=False)
    categories
= CategorySerializer(many=True, required=False)
   
   
class Meta:
        model
= Item
        owner
= serializers.Field(source='owner.username')
        fields
= ('id', 'name', 'description', 'prices', 'categories')
   
   
def create(self, validated_data):
        user
= validated_data.get('user')
   
       
# Get our categories
        category_data
= validated_data.pop('categories')


       
# Create our item
        item
= Item.objects.create(**validated_data)
   
       
# Process the categories. We create any new categories, or return the ID of existing
       
# categories.
       
for category in category_data:
            category
['name'] = category['name'].title()
            category
, created = Category.objects.get_or_create(user=user, **category)
            item
.categories.add(category.id)
       
        item
.save()
   
       
return item


When I try and POST a new item I get the following error:

{
   
"prices": [
       
{
           
"item": [
               
"This field is required."
           
]
       
}
   
]
}


Presumably because the Price serializer has no idea what the ID of the new item is. I've tried overriding this functionality in the `create()` function of my serializer, but it appears as though the serializer's validation is being hit before I have the opportunity to create the item and associate it with the price.

So - How do I create a new item, get the item ID, and then create each of the new prices?

Xavier Ordoquy

unread,
Dec 31, 2014, 4:16:04 AM12/31/14
to django-res...@googlegroups.com
Hi Louis,

It would definitively help to have an example of your POST data.
Please also note that PriceSerializer’s owner field shouldn’t be within the Meta and that ItemSerializer’s create will not be called since it’s the nested serializer and DRF 3.0 only calls the « primary » serializer’s create/update.


Presumably because the Price serializer has no idea what the ID of the new item is. I've tried overriding this functionality in the `create()` function of my serializer, but it appears as though the serializer's validation is being hit before I have the opportunity to create the item and associate it with the price.

So - How do I create a new item, get the item ID, and then create each of the new prices?

--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Louis Lang

unread,
Dec 31, 2014, 10:56:35 AM12/31/14
to django-res...@googlegroups.com
Hi Xavier,
Here is an example of my POST data:

{
   
"name": "Testing",
   
"description": "This is a test",
   
"categories": [
       
{
           
"name": "foo"
       
},
       
{
           
"name": "bar"
       
}
   
],
   
"prices": [
       
{
           
"name": "Red",
           
"cost": 10
       
}
   
]
}

This is being sent to /api/item/ and I had hoped that it would create the item and then call the serializer for price and create those as well (and associate them with the item by the foreignkey). I think this may be a misunderstanding of the serializers on my part. I had assumed that at the very least the ItemSerializer's create/update would be called but that the create/update of PriceSerializer would not be called - So in this case, ItemSerializer is the nested serializer, and not PriceSerializer?
Hi Louis,

To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+unsub...@googlegroups.com.

Xavier Ordoquy

unread,
Dec 31, 2014, 11:09:56 AM12/31/14
to django-res...@googlegroups.com
Le 31 déc. 2014 à 16:56, Louis Lang <louis....@gmail.com> a écrit :

Hi Xavier,
Here is an example of my POST data:

{
    "name": "Testing",
    "description": "This is a test",
    "categories": [
        {
            "name": "foo"
        },
        {
            "name": "bar"
        }
    ],
    "prices": [
        {
            "name": "Red",
            "cost": 10
        }
    ]
}

This is being sent to /api/item/ and I had hoped that it would create the item and then call the serializer for price and create those as well (and associate them with the item by the foreignkey). I think this may be a misunderstanding of the serializers on my part. I had assumed that at the very least the ItemSerializer's create/update would be called but that the create/update of PriceSerializer would not be called - So in this case, ItemSerializer is the nested serializer, and not PriceSerializer?

I’ve been mislead by the fact that the error showed the item was missing. You are right, the ItemSerializer is the top one and the Price one is the nested. Therefore you need to exclude the item field from the Price serializer.

Tip: don’t use exclude, list explicitly the fields.


To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Regards,
Xavier.
Reply all
Reply to author
Forward
0 new messages