Django中的多态性

2 投票
8 回答
3001 浏览
提问于 2025-04-15 14:10

我有以下这些模型。我该如何从实体表中获取继承表(团队和运动员)的unicode?我想显示一个所有实体的列表,如果是团队就显示'名称',如果是运动员就显示'名字'和'姓氏'。

class Entity(models.Model):
  entity_type_list = (('T', 'Team'), ('A', 'Athlete'))
  type = models.CharField(max_length=2, choices=entity_type_list,default='P') 
  pictureurl = models.URLField('Picture Url', verify_exists=False, max_length=255, null=True, blank=True)


class Team(Entity):

  name = models.CharField(max_length=100)

  def __unicode__(self):
    return self.name

class Athlete(Entity):

  firstname = models.CharField(max_length=100)
  lastname = models.CharField(max_length=100)

  def __unicode__(self):
    return '%s %s' % (self.firstname, self.lastname)

8 个回答

0

遍历所有的实体……如果这个实体的类别是'Athlete'(运动员),并且它有名字和姓氏:那就做点事情。

希望这对你有帮助。

编辑:嗯,我好像忘了怎么把这两种实体合并成一个列表。不太确定有没有简单的方法可以做到这一点。

1

在纯Python中,你可以使用 isinstance 这个函数:

class Entity:
    def __init__(self):
        if isinstance(self, Team):
            print 'is team'
        elif isinstance(self, Athlete):
            print 'is athlete'

class Team(Entity):
    def __unicode__(self):
        return 'Team'

class Athlete(Entity):
    def __unicode__(self):
        return 'Athlete'
6

这是Carl Meyer对Paul McMillan之前提到的问题的回答,可能正是你想要的。这个问题有一个细节,在一些回答中没有提到,就是如何从Entity的查询集中获取派生类的实例。

问题

for entity in Entity.objects.all()
  print unicode(entity) # Calls the Entity class unicode, which is not what you want.

解决方案

可以使用上面链接中提到的InheritanceCastModel混入类作为Entity的基类。这样,你就可以将Entity的实例转换为实际的派生类实例。当你想在父类(Entity)上使用查询集,但又想访问派生类的实例时,这个方法特别有用。

class Entity(InheritanceCastModel):
  # your model definition. You can get rid of the entity_type_list and type, as the
  # real_type provided by InheritanceCastModel provides this info

class Athlete(Entity):
  # unchanged

class Team(Entity):
  # unchanged

for entity in Entity.objects.all():
  actual_entity = entity.cast()
  print unicode(actual_entity) # actual entity is a a Team or Athlete

撰写回答