Почему мое поле "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', ...]
Вернуться на верх