Django: доступ к определенному атрибуту нескольких подклассов с наследованием от одного суперкласса

Моя цель - получить доступ к атрибуту подкласса, не зная заранее, какой из двух подклассов был выбран (классы с множественным выбором)

В идеале в суперклассе есть атрибут, который изменяется в зависимости от того, какой подкласс выбран.

Причина в том, что я создал формы непосредственно из подклассов и использую суперкласс в качестве точки входа для доступа к значениям.

Я знаю, что могу использовать true или false с hasattr(horse), но в идеале я спрашиваю, есть ли немного более точное решение, такое как SubClass может сигнализировать SuperClass, какой SubClass использовался.

например, для продукта 8 в моем списке

subclass = getattr(Product(8), 'subclass', 0)
print(subclass)
>> Horse

или же

place = Product.location
Print(place)
>> Stable

Вся "проблема" проистекает из того факта, что я создаю Продукты через Формы Подкласса, в то время как большая часть более поздней логики идет сверху вниз, начиная с Продукта.

class Product(models.Model):
  product_name = models.Charfield(max_length=20)

class Car(Product):
  engine = models.Charfield(max_length=20)
  location = models.Charfield(default="Garage", max_length=20, editable=False)
  product = models.OneToOneField(Product, parent_link=True, on_delete=models.CASCADE)

class Horse(Product):
  saddle_model = models.Charfield(max_length=20)
  location = models.Charfield(default="Stable", max_length=20, editable=False)
  product = models.OneToOneField(Product, parent_link=True, on_delete=models.CASCADE)

1 ответ

Решение

Если вы хотите получить доступ к свойствам других моделей из модели Продукта, вы можете реализовать метод свойств в Продукте, который проверяет обратную связь между ним и связанными с ним моделями и затем возвращает соответствующее местоположение ( https://docs.djangoproject.com/en/2.1/topics/db/examples/one_to_one/).

class Product(models.Model):
    product_name = models.CharField(max_length=20)

    @property
    def location(self):
        """Return the location of the related subclass"""
        if self.car:
            return self.car.location
        elif self.horse:
            return self.horse.location
        else:
            return None

    @property
    def product_subclass(self):
        """Return the location of the related subclass"""
        if self.car:
            return self.car
        elif self.horse:
            return self.horse
        else:
            return None

Это должно позволить вам использовать его так:

car_product = Product.objects.create(product_name="Car Product")
car = Car.objects.create(engine="engine", location="123 Fake Street", product=car_product)
print(car_product.location)  # Prints "123 Fake Street"

horse_product = Product.objects.create(product_name="Horse Product")
horse = Horse.objects.create(saddle_model="Buckingham", location="1982 Old Street", product=horse_product)
print(horse_product.location)  # Prints "1982 Old Street"

Если вы хотите сделать что-то подобное, чтобы вернуть подкласс:

print(car_product.product_subclass)  # Prints <Car object>
print(horse_product.product_subclass)  # Prints <Horse object>

Эти методы свойств требуют, чтобы запрос к базе данных сверялся с таблицами Car и Horse, поскольку отношение хранится в этих таблицах как product_id колонка. Так что, чтобы выяснить, если product.car действителен, ORM выполняет запрос, аналогичный Car.objects.get(product_id=product.pk)

Другие вопросы по тегам