刚刚接触Django,读它的overview 文档,发现在models.py里的类没有定义__init__
方法,而是定义了类变量(Class Variable):
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
而后却能正常初始化实例:
r = Reporter(full_name='John Smith')
我知道这里肯定是用了什么魔法,比如metaclass之类的东西。可是为什么不直接将这些变量定义为在__init__
方法之中的实例变量?
1
RIcter 2014-12-14 13:00:49 +08:00 1
看一下 models.Model 的源码_(:з」∠)_
在 __init__ 里有写..虽然窝看不太懂OAQ |
2
messense 2014-12-14 13:01:00 +08:00 1
用了 metaclass 和 descriptor,建议去读一下 model 部分的源码。
|
3
RIcter 2014-12-14 13:04:09 +08:00 2
另外定义成 __init__ 方法中的变量多丑..
比如: def __init__(self, name, title): 缩缩self.name = name 缩缩self.title = title 缩缩super(SampleModel, self).__init__() ...麻烦死了辣 |
4
bcxx 2014-12-14 13:22:31 +08:00 1
|
5
kidlj OP |
7
messense 2014-12-14 13:37:11 +08:00 2
metaclass 和 descriptor 这些“魔法”可以实现一些很优雅的东西,ORM 是其中之一。我写的 wechatpy 项目用 metaclass 和 descriptor 实现了对微信公众号消息的 mapping 和生成,也比较简单。
https://github.com/messense/wechatpy/blob/master/wechatpy/messages.py#L29 |
8
kidlj OP 找到了这么一条解释:
“ Django provides a metaclass for Model which scans class attributes and converts them to instance attributes but only if they subclass Field.” http://stackoverflow.com/a/22993791 但比起从类变量到实例变量的转化是怎么实现的,我目前更想知道的是为什么不直接使用实例变量,而非要用类变量的方式呢?这个问题可以等到以后再去考察吧。 我想现在先认识到这种使用方法就够了。感谢大家。 |
9
messense 2014-12-14 14:00:13 +08:00 1
@kidlj 使用实例变量的话 Django 不好从 model 生成 SQL 啥的,用类变量通过 metaclass Django 在运行时记录了所有的信息,然后可以做生成 SQL、验证数据啥的。实例变量你再赋值,Field 信息就没了......
|
10
ccdjh 2014-12-14 14:15:10 +08:00
没想过回复的,不小心,不知道,手一抖,点了感谢 @RIcter -_-
为了不让你困惑,告诉你,我是不小心点感谢回复你的,没其他意思。 平时用tornado,自己写一个简单通用于各数据model。只有几行代码。你可以看一下mongodb的例子: https://github.com/ccdjh/boxmongodb 使用StringProperty() 这些是因为, 1,我是通过def __new__(cls,**arg) 返回一个用于检测数据的列表,并且方便输入初始值 2,可以接纳一些设定值 |
11
ccdjh 2014-12-14 17:00:50 +08:00
@messense
谢谢。虽然只有一个文件,你也统统看完并且修改,这是对代码的一种认真认可。 就像小学生作业一样,满篇红红的,搞的自己挺不好意思的哈。 完整的安装文件你可以在这里获取: https://pypi.python.org/pypi/boxmongodb 这本身就是一个demo文件,我并没有释放更新出来。而且有许多错误的地方。 1,安装的时候出现依赖版本错误 2,AuthProperty的__new__问题,值的更新 3,ModelFilter的__new__废除,使用静态函数 还有很多,包括使用到redis和sqlite等。。 并没有贬性的意思。代码修改后,有运行过么?出错误了 就像0 star一样,有人认真我都很开心了。 但你应该使用后,提出使用问题,提出上面的错误,我会超兴奋和高兴。 但你没有使用,但你没有提出bug,而是对我屎一样的代码风格提出纠正更改,我羞愧死了哈。 谢谢! |
12
virusdefender 2014-12-15 00:21:34 +08:00 1
|
13
kfll 2014-12-15 08:21:21 +08:00 via Android
用实例变量的话,继承和覆盖不就显得麻烦了么…
|