Как изменить родительский класс с 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, чтобы убедиться, что выбран только один экземпляр.