覆盖Django序列化器中的'create'函数

时间:2018-10-30 13:30:14

标签: django django-rest-framework django-serializer

我想知道如何处理具有此类模型的POST请求以正确保存传入数据:

class Recipe(models.Model):
    author = models.ForeignKey('auth.user', related_name='recipes', on_delete=models.CASCADE)
    image = models.TextField(default='None')
    name = models.CharField(max_length=100)
    description = models.TextField(default='No description')
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.name

class Ingredient(models.Model):
    image = models.TextField(default='None')
    name = models.CharField(max_length=100)

    description = models.TextField(default='No description')
    price = models.DecimalField(max_digits=8, decimal_places=3)
    unit_price = models.DecimalField(max_digits=8, decimal_places=3)
    unit_quantity = models.CharField(max_length=20)

    def __str__(self):
        return self.name

我想避免重复成分对象,因此为了在配方中提供一定数量的特定成分,我创建了一个RecipesIngredient模型,该模型将成分与配方绑定在一起,但还包含一定数量的该成分:

class RecipesIngredient(models.Model):
        recipe = models.ForeignKey(Recipe, related_name='ingredients', on_delete=models.CASCADE)
        ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
        quantity = models.CharField(max_length=100)

        def __str__(self):
            return self.quantity

我还为这些模型准备了一些序列化器:

class IngredientSerializer(HyperlinkedModelSerializer):
    class Meta:
        model = Ingredient
        fields = (
            'url',
            'image',
            'name',
            'description',
            'price',
            'unit_price',
            'unit_quantity'
        )

class RecipesIngredientSerializer(HyperlinkedModelSerializer):
    ingredient_name = ReadOnlyField(source='ingredient.name')
    ingredient_price = ReadOnlyField(source='ingredient.price')
    ingredient_unit_price = ReadOnlyField(source='ingredient.unit_price')
    ingredient_unit_quantity = ReadOnlyField(source='ingredient.unit_quantity')

    class Meta:
        model = RecipesIngredient
        fields = (
            'url',
            'ingredient_name',
            'quantity',
            'ingredient_price',
            'ingredient_unit_price',
            'ingredient_unit_quantity'
        )

class RecipeListSerializer(HyperlinkedModelSerializer):
    author = ReadOnlyField(source='author.username')
    author_url = ReadOnlyField(source='author.url')

    class Meta:
        model = Recipe
        fields = (
            'url',
            'author',
            'author_url',
            'image',
            'name',
            'description',
            'votes'
        )


class RecipeDetailSerializer(HyperlinkedModelSerializer):
    author = ReadOnlyField(source='author.username')
    author_url = ReadOnlyField(source='author.url')
    ingredients = RecipesIngredientSerializer(many=True)

    class Meta:
        model = Recipe
        fields = (
            'url',
            'author',
            'author_url',
            'image',
            'name',
            'description',
            'ingredients',
            'votes'
        )

但是在这种情况下,我必须首先创建一个Recipe实例并将其保存到DB,然后对Ingredient进行相同操作,以便能够将它们“绑定”到RecipesIngredient中。是否可以通过仅在下面查看一个POST请求来处理这种情况?

#
# path('recipes/', views.RecipeList.as_view(), name='recipe-list')
#
class RecipeList(generics.ListCreateAPIView):
    queryset = Recipe.objects.all()
    serializer_class = RecipeListSerializer

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

@EDIT 我忘了“绕线”,但问题现在已经解决。我已经准备了另一个仅用于创建目的的序列化程序,并重写了此序列化程序的“创建”功能。

class RecipeCreateSerializer(HyperlinkedModelSerializer):
    #author = ReadOnlyField(source='author.username')
    #author_url = ReadOnlyField(source='author.url')
    recipes_ingredients = RecipesIngredientCreateSerializer(many=True)

    def create(self, validated_data):
        recipes_ingredients = validated_data.pop('recipes_ingredients')
        recipe_instance = super().create(validated_data)

        for recipe_ingredient in recipes_ingredients:

            ingredient_data = recipe_ingredient.pop('ingredient')
            ingredient_instance = Ingredient(
                image=ingredient_data['image'],
                name=ingredient_data['name'],
                description=ingredient_data['description'],
                price=ingredient_data['price'],
                unit_price=ingredient_data['unit_price'],
                unit_quantity=ingredient_data['unit_quantity'],
            )
            ingredient_instance.save()


            recipes_ingredient_instance = RecipesIngredient(
                recipe=recipe_instance,
                ingredient=ingredient_instance,
                quantity=recipe_ingredient['quantity']
            )
            recipes_ingredient_instance.save()
        return recipe_instance

    class Meta:
        model = Recipe
        fields = (
            'url',
            'image',
            'name',
            'description',
            'votes',
            'recipes_ingredients',
        )

现在JSON文件看起来也有些不同,但是一切正常:

{
    "image": "image-url",
    "name": "recipes-name",
    "description": "recipes-description",
    "votes": 0,
    "recipes_ingredients": [
        {
            "quantity": "ingredients-quantity",
            "ingredient": {
                "image": "image-url",
                "name": ingredient-name",
                "description": "ingredient-description",
                "price": 3.6,
                "unit_price": 0.36,
                "unit_quantity": "100ML"
            }
        },
        {
            "quantity": "ingredients-quantity",
            "ingredient": {
                "image": "image-url",
                "name": ingredient-name",
                "description": "ingredient-description",
                "price": 0.3,
                "unit_price": 0.3,
                "unit_quantity": "EACH"
            }
        },
        {
            "quantity": "ingredients-quantity",
            "ingredient": {
                "image": "image-url",
                "name": ingredient-name",
                "description": "ingredient-description",
                "price": 2.0,
                "unit_price": 0.8,
                "unit_quantity": "KG"
            }
        }
    ]
}

0 个答案:

没有答案