Django:通过从一个超类继承来访问多个子类的某些属性
Django: Access certain attribute of multiple subclasses with inheritance from one superclass
我的目标是在事先不知道两个子类中选择了哪一个的情况下访问子类的属性(多项选择类)
理想情况下,超类中有一个属性会根据选择的子类而变化。
原因是我直接从子类创建表单,并使用超类作为访问值的入口点。
我知道我可以对 hasattr(horse) 使用 true 或 false,但理想情况下我想问的是是否有更简洁的解决方案,例如 SubClass 可以向 SuperClass 发出使用了哪个 SubClass 的信号。
例如对于我列表中的产品 8
subclass = getattr(Product(8), 'subclass', 0)
print(subclass)
>> Horse
或
place = Product.location
Print(place)
>> Stable
整个"problem"源于我通过子类表单创建产品的事实,同时大部分后来的逻辑都是自上而下的,从产品开始
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)
如果您想从 Product 模型访问其他模型属性,您可以实现 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
这应该允许您像这样使用它:
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"
如果您想做类似于 return 子类的事情:
print(car_product.product_subclass) # Prints <Car object>
print(horse_product.product_subclass) # Prints <Horse object>
这些 属性 方法需要数据库查询来检查车和马 table,因为关系存储在那些 table 上作为 product_id
柱子。因此,为了确定 product.car
是否有效,ORM 执行类似于 Car.objects.get(product_id=product.pk)
的查询
我的目标是在事先不知道两个子类中选择了哪一个的情况下访问子类的属性(多项选择类)
理想情况下,超类中有一个属性会根据选择的子类而变化。
原因是我直接从子类创建表单,并使用超类作为访问值的入口点。
我知道我可以对 hasattr(horse) 使用 true 或 false,但理想情况下我想问的是是否有更简洁的解决方案,例如 SubClass 可以向 SuperClass 发出使用了哪个 SubClass 的信号。
例如对于我列表中的产品 8
subclass = getattr(Product(8), 'subclass', 0)
print(subclass)
>> Horse
或
place = Product.location
Print(place)
>> Stable
整个"problem"源于我通过子类表单创建产品的事实,同时大部分后来的逻辑都是自上而下的,从产品开始
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)
如果您想从 Product 模型访问其他模型属性,您可以实现 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
这应该允许您像这样使用它:
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"
如果您想做类似于 return 子类的事情:
print(car_product.product_subclass) # Prints <Car object>
print(horse_product.product_subclass) # Prints <Horse object>
这些 属性 方法需要数据库查询来检查车和马 table,因为关系存储在那些 table 上作为 product_id
柱子。因此,为了确定 product.car
是否有效,ORM 执行类似于 Car.objects.get(product_id=product.pk)