Django Rest Framework 3.0:保存嵌套,多对一关系

时间:2014-12-31 05:08:47

标签: python django serialization django-rest-framework

我正在尝试使用Django Rest Framework 3.0构建嵌套关系。我已经创建了序列化程序并试图覆盖create()函数。我的模型定义如下:

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()

正如您所知,我的商品可以有多种价格。我的序列化器定义如下:

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

当我尝试发布新项目时:

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

我收到以下错误:

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

大概是因为价格序列化器不知道新商品的ID是什么。我已尝试在我的序列化程序的create()函数中覆盖此功能,但在我有机会创建项目并将其与价格相关联之前,好像序列化程序的验证正在被点击。

那么 - 如何创建新项目,获取项目ID,然后创建每个新价格?

1 个答案:

答案 0 :(得分:5)

问题是您的PriceSerializer正在寻找item密钥,因为它是在Price模型上指定的。这并不是很明显,因为您使用的是Meta.exclude而不是Meta.fields

class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        exclude = ('user',)

与写作相同

class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        fields = ('id', 'item', 'name', 'cost', )

这使得您的问题非常清楚。由于模型上的item字段未设置empty=True(或null=True),因此Django REST Framework会自动generates it as a PrimaryKeyRelatedField required=True。这就是为什么你得到This field is required必需的错误,因为Django REST Framework无法自动检测到它来自已经拥有该字段的父序列化程序。

您可以通过从序列化程序中删除字段来解决此问题,因为它似乎不需要。

class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        fields = ('id', 'name', 'cost', )

这将不再显示item字段,但我怀疑这对您来说实际上不是问题。