【问题标题】:Django: Access certain attribute of multiple subclasses with inheritance from one superclassDjango:从一个超类继承访问多个子类的某些属性
【发布时间】:2019-05-13 01:41:39
【问题描述】:

我的目标是在事先不知道选择了两个子类中的哪一个的情况下访问子类的属性(多选类)

理想情况下,超类中有一个属性会根据选择的子类而变化。

原因是我直接从子类创建了表单,并使用超类作为访问值的入口点。

我知道我可以对 hasattr(horse) 使用 true 或 false,但理想情况下我会问是否有更简洁的解决方案,例如 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)

【问题讨论】:

    标签: django inheritance django-models subclass multiple-choice


    【解决方案1】:

    如果您想从 Product 模型访问其他模型属性,您可以在 Product 上实现 property method,检查它与其相关模型之间的反向关系,然后返回适当的位置 (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) 的查询

    【讨论】:

    • 谢谢,我可以看看我是否会使用 def __str__(self): return self.location 下面的子类会在请求时返回一个干净的变量,例如 horse_product.location >> stable跨度>
    • 由于位置是CharField,它应该总是返回一个干净的变量,就像你提到的那样,不需要覆盖__str__();即打印(horse.location)->“稳定”或打印(horse_product.location)->“稳定”。我更喜欢让实例的__str__() 方法返回对象的人类可读且有意义的定义,即__str__(self): return f"{self.__class__.__name__} #{self.pk} at {self.location}" 这将返回“稳定的产品#1”或“稳定的马#2”,但这是个人喜好。它不应该影响你的程序的逻辑,只是演示。
    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多