Django模型子类化与方法重写问题:基类迭代调用子类方法失效
Django多态模型方法调用解决方案
问题根源
你的原始代码使用Django多表继承时,Owner.objects.all()返回的是Owner类实例,而非子类Industry/Household的实例,因此调用的是基类的dothis方法;此外子类方法中直接引用size/population会触发NameError,需改为self.size/self.population。
一、将Owner设为抽象基类的标准方法
Django中创建抽象模型基类无需继承Python的ABC/ABCMeta,只需在模型的Meta类中设置abstract=True,基类不会生成数据库表,子类自动继承其方法与字段。
修正代码:
from django.db import models class Owner(models.Model): def dothis(self): print('base class dothis was called') class Meta: abstract = True # 标记为抽象基类 class Industry(Owner): size = models.IntegerField(default=1) def dothis(self): print(f'Industry dothis says {self.size}') class Household(Owner): population = models.IntegerField(default=1) def dothis(self): print(f'Household dothis says {self.population}') def do(): Industry.objects.create(size=1) Household.objects.create(population=2) # 抽象基类无数据库表,需合并子类查询结果 all_owners = list(Industry.objects.all()) + list(Household.objects.all()) for owner in all_owners: owner.dothis()
执行后会输出:
Industry dothis says 1 Household dothis says 2
二、替代方案:多表继承+向下转型
若需保留Owner的数据库表(用于存储公共字段),可通过多表继承自动生成的一对一关联字段获取子类实例:
from django.db import models class Owner(models.Model): def dothis(self): # 检测并调用子类方法 if hasattr(self, 'industry'): self.industry.dothis() elif hasattr(self, 'household'): self.household.dothis() else: print('base class dothis was called') class Industry(Owner): size = models.IntegerField(default=1) def dothis(self): print(f'Industry dothis says {self.size}') class Household(Owner): population = models.IntegerField(default=1) def dothis(self): print(f'Household dothis says {self.population}') def do(): Industry.objects.create(size=1) Household.objects.create(population=2) for owner in Owner.objects.all(): owner.dothis()
此方案下,Owner.objects.all()返回的基类实例会自动转发调用子类的dothis方法。
内容的提问来源于stack exchange,提问作者ancient geek
相关产品推荐
相关产品推荐

