我是Django和Python的新手,最近在Django文档中遇到了很多方法,比如Model.get FOO_display()。“帮助”页说,可以用FOO替换字段的名称。我一直在试图弄清楚这在Python中是如何实现的,并研究了“Model”类的来源。 我偶然发现:
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如何将FIELD(或FOO)改为gender呢?是某种Python的“邪恶”符号吗?(对不起,我不能问得更清楚)你能指一下Python手册页吗?
2)为什么Model类的source用前导下划线声明了_get_FIELD_display(),而上面提取的Python doc却没有下划线写“p.get_gender_display()”?再说一遍,你能给我一个Python手册页吗?
类上的magic__getattr__方法可用于实现此类功能。
__getattr__
对于obj.attribute
上不存在attribute
的每个obj.attribute
调用,并且实现可以返回它希望的任何内容。这都是通过元类进行管理的—您将在源代码中看到,模型类定义了一个
__metaclass__
属性,该属性设置为ModelBase
。元类对于类就像类对于实例一样。因此,当Django类被定义为时调用元类。然后元类执行确定模型类属性的各种代码。因此,它遍历在模型类上声明的字段,并将每个字段作为实例属性进行赋值——这就是Django的声明性语法的工作原理。然后它调用每个字段的
contribute_to_class
方法,该方法向类本身添加任何字段特定的方法,其中一个方法是_get_FOO_display
方法。你可以在django/db/models/fields/__init__.py
中看到这个的源代码。为了将
_get_FIELD_display
更改为get_myfieldname_display
,它使用了一种称为“currying”的技术,这意味着它定义了一个新函数,该函数使用定义的参数应用原始方法-在本例中是字段的名称。如果你对这些感兴趣的话,马蒂·阿尔钦的书《Pro Django》有一个很好的解释。
相关问题 更多 >
编程相关推荐