Вложенный сериализатор для многих ко многим - PullRequest
0 голосов
/ 31 мая 2018

Я новичок в Python и Django.Я создаю API с использованием Django-Rest-Framework. Я хочу сериализировать данные, которые могут принимать json в следующем формате:

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

Однако я могу сохранить данные в БД в следующем формате:

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

Я не уверен, как я могу преобразовать словарь в заданное поле.Я знаю о поле списка и список сериализатора , но не знаю, как их использовать.Возможно ли это сделать с помощью модели сериализатора?

Serializer.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

Model.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  

1 Ответ

0 голосов
/ 01 июня 2018

Я бы порекомендовал вам использовать два разных сериализатора для целей создания и другие.Смотрите приведенный ниже фрагмент,
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__'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...