My aim is to access an attribute of a subclass without knowing beforehand which of the two subclasses was choosen (multiple choice classes)
Ideally there is an attribute in the SuperClass that changes depending upon which SubClass was choosen.
The reason is that I have created Forms directly from the SubClasses and use the SuperClass as the entry point for accessing values.
I am aware I can use true or false with hasattr(horse), but ideally I am asking if there is a bit neater solution, such as the SubClass can signal to SuperClass which SubClass was used.
e.g. for product 8 on my list
subclass = getattr(Product(8), 'subclass', 0)
print(subclass)
>> Horse
or
place = Product.location
Print(place)
>> Stable
The whole "problem" stem from the fact that I create Products via SubClass Forms, meanwhile much of the later logic goes top-down, starting with Product
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)
If you want to access the other models properties from the Product model you could implement a property method on Product that inspects the reverse relation between it and its related models and then returns the appropriate location (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
This should allow you to use it like so:
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"
If you'd like to do something similar to return the subclass:
print(car_product.product_subclass) # Prints <Car object>
print(horse_product.product_subclass) # Prints <Horse object>
These property methods require a database query to check with the Car and Horse table's, since the relation is stored on those tables as the product_id
column. So to figure out if product.car
is valid, the ORM does a query similar to Car.objects.get(product_id=product.pk)