Как обновить поле сериализатора для отношения m2m - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь обновить отправленные данные, применяя метод update () в SerializerClass.Однако я не знаю, как получить доступ к текущему компоненту текущего экземпляра, а также я не знаю, как перебирать проверенные данные так, чтобы я мог правильно назначить ключ и значения.Любой совет будет оценен!

Мой сериализатор

class RecipeSerializer(ModelSerializer):
    ingredients = IngredientSerializer(many=True)
    owner = ReadOnlyField(source='owner.username')

    class Meta:
        fields = ['owner', 'name', 'description', 'image', 'ingredients']
        model = Recipe

    def create(self, validated_data):
        ingredient_datas = validated_data.pop('ingredients')
        recipe = Recipe.objects.create(**validated_data)
        for ingredient_data in ingredient_datas:
            recipe.ingredients.create(**ingredient_data)
        return recipe

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.description = validated_data.get('description', instance.description)
        instance.image = validated_data.get('image', instance.image)

        for ingredient in validated_data.get('ingredients'):
            for key, value in ingredient.items():
                print(key, value)
                instance.ingredient.name = value
                instance.ingredient.amount = value
        instance.save()
        return instance

Мои модели

class Recipe(models.Model):
    owner = models.ForeignKey('auth.User', related_name='recipes', on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=200, blank=True)
    image = models.CharField(max_length=100, blank=True)
    ingredients = models.ManyToManyField(Ingredient, related_name='recipes')

class Ingredient(models.Model):
    name = models.CharField(max_length=50)
    amount = models.IntegerField(default=1)

Некоторые выходы оболочки окна

print (validated_data)

{'name': 'bedddef', 'description': 'gdddoot', 'image': 'httpdddlo', 'ingredients': [OrderedDict([('name', 'tomatoes'), ('amount', 2)]), OrderedDict([('name', 'bread'), ('amount', 3)])]}

для ключа, значение в component.items ():
print (ключ, значение)

name tomatoes
amount 2
name bread
amount 3

Недавно (сегодня) Я снова воссоздал весь API, потому что я потерял его.Я попытался использовать тот же код медведя, который был предложен для метода update () с использованием Ingredient.objects.get_or_create (), но я получил сообщение об ошибке.

MultipleObjectsReturned в / api / recipes / 3 / get () вернул больше, чемодин ингредиент - он возвратил 2!

Из-за ошибки, которую я заменил get_or_create () на просто create (), это было бы плохим решением?

   def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.descriptions = validated_data.get('descriptions', instance.descriptions)
        instance.image = validated_data.get('image', instance.image)
        ingredients = []
        for ingredient in validated_data.get('ingredients'):
            obj = Ingredient.objects.create(**ingredient)
            ingredients.append(obj)
        print(ingredients)
        instance.ingredients.set(ingredients)
        instance.save()
        return instance

1 Ответ

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

вы можете использовать set метод m2m RelatedManager

def update(self, instance, validated_data):
    instance.name = validated_data.get('name', instance.name)
    instance.description = validated_data.get('description', instance.description)
    instance.image = validated_data.get('image', instance.image)
    ingredients = []
    for ingredient in validated_data.get('ingredients'):
        obj, _ = Ingredient.objects.get_or_create(**ingredient)
        ingredients.append(obj)
    instance.ingredients.set(ingredients)
    #                 ^^^^^^
    instance.save()
    return instance

детали: get_or_create кортеж возврата экземпляра модели и значение bool создает новый экземпляр, нонам не нужен bool, поэтому чтобы сделать код более читабельным, просто присвойте значение переменной _

obj, _ = Ingredient.objects.get_or_create(**ingredient)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...