11

一般来说,我不熟悉 python 覆盖方法和使用 super() 的方式。

问题是:我可以覆盖get_FOO_display()吗?

class A(models.Model):
   unit = models.IntegerField(choices=something)

   def get_unit_display(self, value):
     ... use super(A, self).get_unit_display() 

我想覆盖 get_FOO_display() 因为我想复数我的显示。

super(A, self).get_unit_display()不起作用。

4

4 回答 4

10

通常,您只需覆盖一个方法,如您所示。但这里的技巧是该get_FOO_display方法不存在于超类中,因此调用该super方法将什么都不做。该方法由元类添加到模型时由字段类动态添加 - 请参见此处的源代码(编辑:过时链接为永久链接)。

您可以做的一件事是为您的unit字段定义一个自定义 Field 子类,并覆盖contribute_to_class,以便它构造您想要的方法。不幸的是,这有点棘手。

(我不明白你的第二个问题。你到底在问什么?)

于 2012-12-18T10:36:23.597 回答
1

现在在 Django > 2.2.7

恢复了覆盖 get_FOO_display() (#30931) 的能力。

您可以覆盖:


    class FooBar(models.Model):
        foo_bar = models.CharField(_("foo"),  choices=[(1, 'foo'), (2, 'bar')])
    
    
   
        def get_foo_bar_display(self):
            return "something"

于 2020-10-19T23:18:37.547 回答
0

你可以这样做:

  1. 覆盖 DjangoIntegerField以复制您的get_FOO_display函数:

    class MyIntegerField(models.IntegerField):
        def contribute_to_class(self, cls, name, private_only=False):
            super(MyIntegerField, self).contribute_to_class(cls, name, private_only)
            if self.choices is not None:
                display_override = getattr(cls, 'get_%s_display' % self.name)
                setattr(cls, 'get_%s_display_override' % self.name, display_override)
    
  2. 在您的班级中,将您的选择字段替换为MyIntegerField

    class A(models.Model):
       unit = MyIntegerField(choices=something)
    
  3. 最后,使用复制函数返回超值:

       def get_unit_display(self, value):
           if your condition:
              return your value
           return self.get_unit_display_override()
    
于 2020-02-26T17:30:48.597 回答
-3

您应该能够通过在子类上创建具有相同名称的方法来覆盖超类上的任何方法。不考虑参数签名。例如:

class A(object):
    def method(self, arg1):
        print "Method A", arg1

class B(A):
    def method(self):
        print "Method B"

A().method(True) # "Method A True"
B().method() # "Method B"

在 get_unit_display() 的情况下,如果要更改显示值,则根本不必调用 super(),但如果要使用 super(),请确保使用正确的签名调用它, 例如:

class A(models.Model):
    unit = models.IntegerField(choices=something)

    def get_unit_display(self, value):
        display = super(A, self).get_unit_display(value)
        if value > 1:
            display = display + "s"
        return display

请注意,我们将值传递给 super() 的 get_unit_display()。

于 2012-12-18T01:42:04.013 回答