简体   繁体   English

Django:覆盖 get_FOO_display()

[英]Django: override get_FOO_display()

In general, I'm not familiar with python's way of overriding methods and using super().总的来说,我不熟悉 python 重写方法和使用 super() 的方式。

question is: can I override get_FOO_display() ?问题是:我可以覆盖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() 

I want to override get_FOO_display() because I want to pluralize my display.我想覆盖 get_FOO_display() 因为我想使我的显示复数化。

But super(A, self).get_unit_display() doesn't work.但是super(A, self).get_unit_display()不起作用。

Normally you would just override a method as you have shown.通常,您只需覆盖您显示的方法。 But the trick here is that the get_FOO_display method is not present on the superclass, so calling the super method will do nothing at all.但这里的技巧是get_FOO_display方法不存在于超类中,因此调用super方法将什么都不做。 The method is added dynamically by the field class when it is added to the model by the metaclass - see the source here (EDIT: outdated link as permalink ).当元类将方法添加到模型时,该方法由字段类动态添加 - 请参阅此处的源代码(编辑:过时链接为永久链接)。

One thing you could do is define a custom Field subclass for your unit field, and override contribute_to_class so that it constructs the method you want.您可以做的一件事是为您的unit字段定义一个自定义 Field 子类,并覆盖contribute_to_class以便它构造您想要的方法。 It's a bit tricky unfortunately.不幸的是,这有点棘手。

(I don't understand your second question. What exactly are you asking?) (我不明白你的第二个问题。你到底在问什么?)

Now in Django > 2.2.7 :现在在 Django > 2.2.7 中

Restored the ability to override get_FOO_display() (#30931).恢复了覆盖 get_FOO_display() (#30931) 的能力。

You can override:您可以覆盖:


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

You could do it this way:你可以这样做:

  1. Override the Django IntegerField to make a copy of your get_FOO_display function:覆盖 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. In your class, replace your choice field with MyIntegerField :在您的课程中,用MyIntegerField替换您的选择字段:

     class A(models.Model): unit = MyIntegerField(choices=something)
  3. Finally, use the copy function to return the super value:最后,使用复制函数返回超值:

     def get_unit_display(self, value): if your condition: return your value return self.get_unit_display_override()

You can't directly call super() because the original method doesn't "exist" yet on the parent model.您不能直接调用super() ,因为原始方法在父 model 上还不“存在”。

Instead, call self._get_FIELD_display() with the field object as its input.相反,调用self._get_FIELD_display()并将字段 object 作为其输入。 The field object is accessible through the self._meta.get_field() method.字段 object 可通过self._meta.get_field()方法访问。

def get_unit_display(self):
    singular = self._get_FIELD_display(self._meta.get_field('unit'))
    return singular + 's'

You should be able to override any method on a super class by creating a method with the same name on the subclass.您应该能够通过在子类上创建具有相同名称的方法来覆盖超类上的任何方法。 The argument signature is not considered.不考虑参数签名。 For example:例如:

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"

In the case of get_unit_display(), you do not have to call super() at all, if you want to change the display value, but if you want to use super(), ensure that you're calling it with the correct signature, for example:在 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

Note that we are passing value to the super()'s get_unit_display().请注意,我们将值传递给 super() 的 get_unit_display()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM