Почему мое поле "id" исчезает в моем сериализаторе (manytomany)?
У меня есть объект "PriceTable", который может содержать несколько объектов "PriceLine" с отношением manytomany.
Я использую django rest framework для публикации api и хотел бы, чтобы при использовании PUT или PATCH для PriceTable, я также мог изменять содержимое PriceLine. Цель состоит в том, чтобы иметь уникальный метод UPDATE, чтобы иметь возможность изменять экземпляры этих двух объектов.
Мои модели:
class PriceTable(models.Model):
name = models.CharField(_('Name'), max_length=255)
client = models.ForeignKey(
"client.Client",
verbose_name=_('client'),
related_name="price_table_client",
on_delete=models.CASCADE
)
lines = models.ManyToManyField(
'price.PriceLine',
verbose_name=_('lines'),
related_name="price_table_lines",
blank=True,
)
standard = models.BooleanField(_('Standard'), default=False)
class Meta:
verbose_name = _("price table")
verbose_name_plural = _("price tables")
def __str__(self):
return self.name
class PriceLine(models.Model):
price = models.FloatField(_('Price'))
product = models.ForeignKey(
"client.Product",
verbose_name=_('product'),
related_name="price_line_product",
on_delete=models.CASCADE,
)
class Meta:
verbose_name = _("price line")
verbose_name_plural = _("price line")
def __str__(self):
return f"{self.product.name} : {self.price} €"
Я хочу иметь возможность отправить JSON такого формата, чтобы изменить как таблицу, так и ее строки:
{
"id": 16,
"lines": [
{
"id": 1,
"price": 20.0,
"product": 1
},
{
"id": 2,
"price": 45.0,
"product": 2
}
],
"name": "test"
}
Для этого я пытаюсь переопределить метод update моего сериализатора:
class PriceTableSerializer(serializers.ModelSerializer):
"""
PriceTableSerializer
"""
lines = PriceLineSerializerTest(many=True)
class Meta:
model = PriceTable
exclude = ['standard', 'client',]
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
lines = validated_data.get('lines')
print(lines)
# not python code
# for target_line in lines:
# if instance.id == target_line.id
# instance.price = target_line.price
# ...
return instance
5 закомментированных строк - это логика, которую я хочу реализовать. Я хочу просматривать полученный массив строк и если id этой строки равен id строки в моем экземпляре, я изменяю значения этой строки.
Проблема в том, что id исчезает. Когда я печатаю переменную lines
, я получаю следующее:
[OrderedDict([('price', 20.0), ('product', <Product: Test import2>)])]
OrderedDict([('price', 20.0), ('product', <Product: Test import2>)])
Что случилось с идентификатором?
Как сказано в документации https://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-update:
Вам необходимо добавить явное поле id в сериализатор экземпляра. По умолчанию неявно генерируемое поле id помечено как read_only. Это приводит к тому, что оно будет удаляться при обновлении. Когда вы объявите его явно, оно будет доступно в методе обновления сериализатора списка.
Так что вы должны объявить id
себя способным использовать это:
class PriceLineSerializerTest(serializers.ModelSerializer):
id = serializers.IntegerField()
class Meta:
model = PriceLine
exclude = ['id', ...]