get_FIELD_display(在django中)如何工作?

时间:2011-04-20 12:24:50

标签: python django

我是Django和Python的新手,最近在Django文档中遇到过许多方法,比如Model.get_FOO_display()。帮助页面说您可以用FOO替换字段的名称。我一直试图弄清楚Python中的可能性,并研究了模型'阶级。 在那里我遇到了这个:

    def _get_FIELD_display(self, field):
        value = getattr(self, field.attname)
        return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True)

我无法理解Python中的可能性如何: 1)写这个

class Person(models.Model):
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
p = Person(name='John', gender='M')

p.get_gender_display()

那么,Python如何改变'将性别(或FOO)纳入性别?它是某种Python' wicked'符号? (对不起,我不能更清楚地问)Coud你指向一些Python手册页吗?

2)为什么来自Model类的源使用前导下划线声明_get_FIELD_display(),但是上面的Python doc extract" p.get_gender_display()"没有下划线?再说一次,你能为此给出一个Python手册页吗?

2 个答案:

答案 0 :(得分:23)

这是通过元类管理的 - 您将在源代码中看到Model类定义了__metaclass__属性,该属性设置为ModelBase。元类属于类,类是一个实例。

因此,当Django类定义时,会调用元类。然后,元类执行各种代码,这些代码确定模型类的属性。因此,它遍历模型类中声明的字段,并将每个字段分配为实例属性 - 这就是Django的声明性语法的工作原理。然后,它调用每个字段的contribute_to_class方法,该方法将任何特定于字段的方法添加到类本身 - 其中一种方法是_get_FOO_display方法。您可以在django/db/models/fields/__init__.py

中查看此内容

为了将_get_FIELD_display更改为get_myfieldname_display,它使用了一种称为“currying”的技术,这意味着它定义了一个新函数,该函数将原始方法应用于已定义的参数 - 在这种情况下,该字段的名称。

如果你对这一切感兴趣,Marty Alchin的书Pro Django有一个很好的解释。

答案 1 :(得分:2)

类上的魔术__getattr__方法可用于实现此类功能。 __getattr__obj.attributeattribute不存在obj的每个{{1}}都会调用{{1}},并且实现可以返回它想要的任何内容。