Django:覆盖get_FOO_display()

时间:2012-12-18 01:27:22

标签: python django

一般来说,我不熟悉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 个答案:

答案 0 :(得分:8)

通常,您只需覆盖已显示的方法。但这里的诀窍是超类上没有get_FOO_display方法,所以调用super方法根本不会做任何事情。当元类通过元类添加到模型时,该方法由字段类动态添加 - 请参阅the source here(编辑:过时的链接为permalink)。

您可以做的一件事是为unit字段定义自定义字段子类,并覆盖contribute_to_class,以便构建所需的方法。不幸的是,它有点棘手。

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

答案 1 :(得分:0)

您可以这样操作:

  1. 覆盖Django IntegerField,以复制您的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()
    

答案 2 :(得分:0)

现在在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"

答案 3 :(得分:-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(),请确保使用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()。