【问题标题】:Nested Serializer for Many to Many多对多的嵌套序列化器
【发布时间】:2018-11-10 12:16:39
【问题描述】:

我是 Python 和 Django 的新手。我正在使用 Django-Rest-Framework 创建 api 我想序列化可以接受以下格式的 json 的数据:

{
"ingredients": ["Sugar","Egg"],
"name": "Cake",
"description": "Dinner Food",
"directions": "direction1"
}

但是我能够以以下格式将数据保存在 db 中:

{
"ingredients": [{"name":"Cake"},{"name":"Egg"}],
"name": "Rice",
"description": "Dinner Food",
"directions": "direction1"
}

我不确定如何将字典转换为设置字段。我知道List fieldlist serialiser 但不知道如何使用它们。 是否可以使用模型序列化器来做到这一点?

序列化器.py

class IngredientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Ingredient
        fields = '__all__'


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

        class Meta:
            model = Recipe
            fields = '__all__'

    def create(self, validated_data):
        ingredients_data = validated_data.pop('ingredients')
        print(ingredients_data)
        recipe = Recipe.objects.create(**validated_data)
        for ingredient in ingredients_data:
            ingredient, created = Ingredient.objects.get_or_create(name=ingredient['name'])
            recipe.ingredients.add(ingredient)
        return recipe

模型.py

class Ingredient(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Recipe(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)
    directions = models.TextField()
    ingredients = models.ManyToManyField(Ingredient)

    def __str__(self):
        return self.name

view.py

class RecipieView(viewsets.ModelViewSet):
    queryset = Recipe.objects.all()
    serializer_class = RecipeSerializer


class IngredientView(viewsets.ModelViewSet):
    queryset = Ingredient.objects.all()
    serializer_class = IngredientSerializer  

【问题讨论】:

    标签: python django django-models django-rest-framework


    【解决方案1】:

    我建议您使用两个不同的序列化程序来创建和其他目的。请参阅下面的 sn-p,
    views.py

    class RecipieView(viewsets.ModelViewSet):
        queryset = Recipe.objects.all()
        serializer_class = RecipeMainSerializer
    
        def get_serializer_class(self):
            if self.action == 'create':
                return RecipeCreateSerializer
            return RecipeMainSerializer
    


    serializer.py

    class RecipeCreateSerializer(serializers.ModelSerializer):
        ingredients = serializers.ListField(write_only=True)
    
        class Meta:
            model = Recipe
            fields = '__all__'
    
        def create(self, validated_data):
            ingredients_data = validated_data.pop('ingredients')
            recipe = Recipe.objects.create(**validated_data)
            for ingredient in ingredients_data:
                ingredient, created = Ingredient.objects.get_or_create(name=ingredient)
                recipe.ingredients.add(ingredient)
            return recipe
    
    
    class RecipeMainSerializer(serializers.ModelSerializer):
        ingredients = IngredientSerializer(many=True)
    
        class Meta:
            model = Recipe
            fields = '__all__'
    

    【讨论】:

    • 如果您可以将我重定向到某些资源以使我准确了解流程周期并且可以发布一个包含 json 数据的文件以流式传输和摄取到数据库中,那将会很有帮助。我认为解析文件并发送多个 post 请求不是理想的解决方案
    • 您好,感谢您对此提出的建议,但您究竟为什么要推荐两种不同的序列化器?
    • 正如 OP 所提到的,您的 HTTP GET 方法和 HTTP POST 方法需要不同的行为。您可以覆盖序列化程序中的一些方法,以便避免使用 multiple 序列化程序。希望它在这里 :) @math
    【解决方案2】:

    我们可以像这样更好地重构@JPG 序列化器:

    class RecipeMainSerializer(serializers.ModelSerializer):
        ingredients = IngredientSerializer(many=True)
    
        class Meta:
            model = Recipe
            fields = '__all__'
    
    class RecipeCreateSerializer(RecipeMainSerializer):
        ingredients = serializers.ListField(write_only=True)
    
        def create(self, validated_data):
            ingredients_data = validated_data.pop('ingredients')
            recipe = Recipe.objects.create(**validated_data)
            for ingredient in ingredients_data:
                ingredient, created = Ingredient.objects.get_or_create(name=ingredient)
                recipe.ingredients.add(ingredient)
            return recipe
    
    

    这改进了dry 我们在更复杂的序列化器中的代码原理

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 2021-06-21
      • 1970-01-01
      • 2016-10-04
      • 2022-12-12
      • 1970-01-01
      • 2020-09-03
      相关资源
      最近更新 更多