DRF:深度大于1的嵌套序列化器

时间:2018-10-01 08:23:39

标签: python django django-rest-framework

我正在研究“嵌套嵌套”序列化器,其中有一个嵌套的序列化器嵌套在另一个序列化器中。这是一项烹饪服务,其中食谱具有多个方向,每个方向具有多种成分。我用外键进行设置。

这是我的模特:

class Category(models.Model):
    """Model representing a recipe category"""
    name = models.CharField(max_length=200, help_text="Enter a recipe category (e.g Baking)")

    def __str__(self):
        """String for representing the Model object."""
        return self.name

class Ingredient(models.Model):
    """Model representing an ingredient in a direction"""
    name = models.CharField(max_length=250, help_text="The ingredient's name")
    quantity = models.CharField(max_length=200, help_text="How much of this ingredient.")
    direction = models.ForeignKey("Direction", help_text="This ingredient's direction", on_delete=models.CASCADE, related_name='ingredients')

    def __str__(self):
        """String for representing this recipe ingredient"""
        return f'{self.quantity} {self.ingredient}'

class Direction(models.Model):
    """Model representing a step in a recipe"""
    title=models.CharField(max_length=200)
    text=models.TextField(blank=True, help_text="Describe this step.")

    recipe=models.ForeignKey("Recipe", help_text="This direction's recipe", on_delete=models.CASCADE, related_name='directions')


    def __str__(self):
        """String for representing the Direction"""
        return self.title

class Recipe(models.Model):
    """Model representing a recipe."""
    title = models.CharField(max_length=200)

    notes = models.TextField(max_length=1000, help_text="Enter notes, reviews, ...")

    photos = models.ImageField(null=True, blank=True)

    category = models.ForeignKey(Category, help_text="This recipe's category", on_delete=models.CASCADE, related_name='recipes')

    def __str__(self):
        """String for representing the Model object."""
        return self.title

    def get_absolute_url(self):
        """Returns the url to access a detail record for this recipe."""

我读了docs,以为我可以在另一个嵌套嵌套序列化器中使用,这使我犯了一个错误,指出“禁止直接分配给相关集合的反面。”

然后我通过使用以下序列化程序使其工作:

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('name',)

    def create(self, validated_data):
        category = Category.objects.create(**validated_data)
        return category


class IngredientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ingredient
        fields = ('quantity', 'name',)

    def create(self, validated_data):
        ingredient = Ingredient.objects.create(**validated_data)
        return ingredient

    def update(self, instance, validated_data):
        instance.quantity = validated_data.get('quantity', instance.quantity)
        instance.name = validated_data.get('name', instance.name)
        instance.direction = validated_data.get('direction', instance.direction)
        instance.save()
        return instance

class DirectionSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(many=True)

    class Meta:
        model = Direction
        fields = ('title', 'text', 'ingredients', )

    def create(self, validated_data):
        direction = Direction.objects.create(**validated_data)

        return direction

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.text = validated_data.get('text', instance.text)
        instance.recipe = validated_data.get('recipe', instance.recipe)

        instance.save()
        return instance


class RecipeSerializer(serializers.ModelSerializer):
    directions = DirectionSerializer(many=True)
    category = CategorySerializer()

    class Meta:
        model = Recipe
        fields = ('title', 'notes', 'photos', 'category', 'directions')

    def create(self, validated_data):
        directions_data = validated_data.pop('directions')
        category_data = validated_data.pop('category')
        category = Category.objects.create(**category_data)
        validated_data["category"] = category
        recipe = Recipe.objects.create(**validated_data)
        recipe.category = category
        for direction_data in directions_data:
            ingredients_data = direction_data.pop("ingredients")
            direction = Direction.objects.create(recipe=recipe, **direction_data)
            for ingredient_data in ingredients_data:
                Ingredient.objects.create(direction=direction, **ingredient_data)
        return recipe

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.notes = validated_data.get('notes', instance.notes)
        instance.photos = validated_data.get('photos', instance.photos)
        instance.category = validated_data.get('category', instance.category)

        instance.save()
        return instance

我不确定,在这一点上实际上需要什么。基本上,我在食谱的create()函数中创建嵌套结构。

现在真正的问题是: 感觉确实像黑客一样。这是实现多个嵌套序列化器的正确方法吗?

如果我这样做,我是否还需要create()和update()函数?

非常感谢您。

0 个答案:

没有答案