用Django继承来区分父模型的子项

时间:2010-02-04 18:40:25

标签: python django

基本上我有一个名为“Program”的Base类。然后我有更多使用Program作为基类的特定程序模型类型。对于我99%的需求,我不关心程序是否是特定的子类型之一。当然,有1%的时间我想知道它是否是其中一个孩子。

问题在于,如果我说,一个SwimProgram模型和一个使用Program作为基础的CampProgram模型,那么在没有一堆try / except块的情况下找出它们是有问题的。我想要的是以下内容:

program = models.Program.objects.get(id=15)
if program.swimprogram:
    ## do stuff
elif program.campprogram:
    ## do stuff
else:
    ## do other stuff

当然这会抛出DoesNotExist异常。我可以使用更粗糙的try / excepts,或者我可以让Program有一个'type'字段,孩子们设置保存。两者都是可行的,但我很好奇是否有人有更好的方法。

3 个答案:

答案 0 :(得分:4)

你试过hasattr()吗?像这样:

if hasattr(program, 'swimprogram'):
    # ...
elif hasattr(program, 'campprogram'):
    # ...

如果您不确定此方法,请先在简单的测试应用中试用。这里有两个简单的模型,它们应该显示它是否适用于您以及您正在使用的django版本(在django-1.1.1中测试)。

class Archive(models.Model):
    pub_date = models.DateField()

    def __unicode__(self):
        return "Archive: %s" % self.pub_date

class ArchiveB(Archive):
    def __unicode__(self):
        return "ArchiveB: %s" % self.pub_date

然后在shell中旋转它:

> a_id = Archive.objects.create(pub_date="2010-10-10").id
> b_id = ArchiveB.objects.create(pub_date="2011-11-11").id
> a = Archive.objects.get(id=a_id)
> b = Archive.objects.get(id=b_id)
> (a, b) # they both look like archive objects
(<Archive: Archive: 2010-10-10>, <Archive: Archive: 2011-11-11>)
> hasattr(a, 'archiveb')
False
> hasattr(b, 'archiveb') # but only one has access to an ArchiveB
True

答案 1 :(得分:1)

几个星期前,django-developers邮件列表中的某个人为Django的ORM引入了一个非常有趣的扩展,它使QuerySets返回子类对象而不是父类的对象。你可以在这里阅读所有相关内容:

http://bserve.webhop.org/wiki/django_polymorphic

我自己还没有尝试过(但肯定会),但它似乎适合你的用例。

答案 2 :(得分:0)

//更新

正如对这篇文章的评论所指出的,我的问题是错误的。以下答案无法解决问题。


嗨f4nt,

我现在能想到的最简单的方法如下:

program = models.Program.objects.get(id=15)

if program.__class__.__name__ == 'ModelA':
  # to something

if program.__class__.__name__ == 'ModelB':
  # to something

为了使这更好一点,你可以在基本模型中编写一个方法:

class MyModel(models.Model):

  def instanceOfModel(self, model_name):
    return self.__class__.__name__ == model_name

这样来自上面的代码看起来像这样:

program = models.Program.objects.get(id=15)

if program.instanceOfModel('ModelA'):
  # to something

if program.instanceOfModel('ModelB'):
  # to something

但是你可以想象这很难看。您可以查看content type框架,它可以帮助您做同样的事情,除了更加优雅。

希望有所帮助!