在django模型中使用python超级函数

时间:2011-08-21 23:21:39

标签: python django super

这是我正在经历的django教程中的一些代码。我以前从来没有遇到python中的超级函数,它在这里使用的方式与我在网上看到的例子不同。即,通常当你使用超级时,你不是有多个班级吗?它在最后一行:super(Snippet, self).save(force_insert, force_update) 你能解释一下那里发生了什么,以及另一种写作方式。看起来似乎保存方法在这里调用自己?

class Snippet(models.Model):
    title = models.CharField(max_length=255)
    language = models.ForeignKey(Language)
    author = models.ForeignKey(User)
    description = models.TextField()
    description_html = models.TextField(editable=False)
    code = models.TextField()
    highlighted_code = models.TextField(editable=False)
    tags = TagField()
    pub_date = models.DateTimeField(editable=False)
    updated_date = models.DateTimeField(editable=False)

    class Meta:
        ordering = ['-pub_date']

    def __unicode__(self):
        return self.title

    def save(self, force_insert=False, force_update=False):
        if not self.id:
            self.pub_date = datetime.datetime.now()
        self.updated_date = datetime.datetime.now()
        self.description_html = markdown(self.description)
        self.highlighted_code = self.highlight()
        super(Snippet, self).save(force_insert, force_update)

2 个答案:

答案 0 :(得分:26)

super(Snippet, self)会导致Python查看自我类MROself.__class__.mro()以查找Snippet之后列出的 next 类。它返回一个super对象,它充当该类的代理。也就是说,调用super对象上的方法就像在类上调用该方法一样。

super(Snippet, self).save(...)调用该类的save方法,self绑定到第一个参数。

因此super(Snippet, self).save(...)不会调用Snippet的{​​{1}}方法;它将调用其他类的save方法。很容易认为这个“其他类”是save的“父类”或“超类”,也就是说, Snippet,但这可能不是真的,以这种方式逮捕models.Model是完全错误的。哪个类super最终代表取决于super(Snippet, self),特别是其类的MRO。

可以找到selfMRO(包括图片!)的非常好的描述here

答案 1 :(得分:4)

我不会再解释unutbu在超类上解释的内容,但是使用以下代码获得相同的效果:

models.Model.save(self, force_insert, force_update)

这不是更好的编写方式,因为如果你通过在Model和Snippet之间添加一个中间类来改变类继承,你也必须改变这一行(你很可能会忘记)。无论如何,要知道这是件好事。

我还可以补充一点,只有你继承的类从object扩展,super指令才有效,否则会出现异常。