#django #django-rest-framework
Вопрос:
У меня есть объект «Цена», который может содержать несколько объектов «Цена» с множеством отношений.
Я использую платформу django rest для публикации api, и я хотел бы, чтобы при использовании PUT или PATCH в таблице цен я также мог изменять содержимое PriceLine. Цель состоит в том, чтобы иметь уникальный метод ОБНОВЛЕНИЯ, позволяющий изменять экземпляры 2 объектов.
Мои модели:
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"
}
Для этого я пытаюсь переопределить метод обновления моего сериализатора:
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 прокомментированных строк-это логика, которую я хотел бы реализовать.
Я хочу просмотреть полученный массив строк, и если идентификатор этой строки равен идентификатору строки в моем экземпляре, я изменяю значения этой строки.
Проблема в том, что идентификатор исчезает. Когда я печатаю lines
переменную, я получаю это:
[OrderedDict([('price', 20.0), ('product', <Product: Test import2>)])]
OrderedDict([('price', 20.0), ('product', <Product: Test import2>)])
Что случилось с удостоверением личности?
Комментарии:
1. Он очищается в
Product
объект.2. Я не понимаю. У меня проблема не в исчезновении идентификатора продукта, а в исчезновении идентификатора объекта PriceLine. (строки полей json)
3. Это поле в
PriceLineSerializerTest
сериализаторе?4. да,
fields = ('id', 'price', 'product',)
вPriceLineSerializerTest
5. Если я поставлю
id = serializers.IntegerField()
, это сработает, но это безумие ….
Ответ №1:
Как говорится в документах в https://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-update:
Вам нужно будет добавить явное поле идентификатора в сериализатор экземпляра. Неявно сгенерированное поле идентификатора по умолчанию помечено как только для чтения. Это приводит к его удалению при обновлении. Как только вы объявите его явно, он будет доступен в методе обновления сериализатора списков.
Поэтому вы должны заявить id
о себе за то, что можете использовать это:
class PriceLineSerializerTest(serializers.ModelSerializer):
id = serializers.IntegerField()
class Meta:
model = PriceLine
exclude = ['id', ...]