Как изменить родительский класс с models.Model на PolymorphicModel

У меня есть две модели django, Tomato и Potato. На обе модели многократно ссылаются в моем проекте.

Недавно я создал поле внешнего ключа в третьей модели, ShoppingBag, которая должна содержать по одному экземпляру либо Tomato, либо Potato.

Мой первый подход заключался в создании пустого (поскольку у помидора и картофеля нет общих полей) суперкласса Buyable, который наследует PolymorphicModel.

Затем я установил в ShoppingBag.myforeignkey ссылающуюся модель, чтобы она принимала экземпляры Buyable, и подумал, что на этом все закончится.

Сейчас я сталкиваюсь с большим количеством ошибок, в основном потому, что Potato.id и Tomato.id заменяются на .buyable_ptr, а уже существующим полям внешнего ключа и m2m Potato и Tomato это не очень нравится.

Я хотел спросить, есть ли официальный способ столкнуться с переходом от одного родителя к другому или альтернативный, более простой способ решить эту проблему.

Я создал функцию, которая генерирует новый экземпляр суперкласса и возвращает его id. Затем я установил эту функцию в качестве значения по умолчанию в файле миграции. Решение не сработало, так как сгенерированный id всегда был равен 1.

import Buyable


def generate_id():
    new_instance = Buyable()
    new_instance.save()
    return new_instance

Я реализовал его через наследование моделей.

Я не применял абстракцию, потому что между помидором и картофелем нет общей части.

class Vegetable(models.Model):
    pass


class ShoppingBag(models.Model):
    vegetable = models.ForeignKey(Vegetable, on_delete=models.SET_NULL, null=True)


class Potato(Vegetable):
    potato_field = models.CharField(max_length=128)


class Tomato(Vegetable):
    tomato_field = models.CharField(max_length=128)
    

В приведенном выше коде помидор и картофель также представлены одним объектом модели под названием Vegatable.

Вот почему, когда мы создаем объект модели ShoppingBag, мы можем выбрать только один из объектов моделей Tomato и Potato.

Мой коллега предложил новый подход.

Я добавлю два поля внешнего ключа в ShoppingBag и выполню проверку xor в методе save или clean, чтобы убедиться, что выбран только один экземпляр.

Вернуться на верх