gpt4 book ai didi

python - 如何做类似 Django 模型的元类技巧

转载 作者:太空狗 更新时间:2023-10-30 03:00:48 24 4
gpt4 key购买 nike

我正在为我的研究项目使 Django 像 ORM 一样,因为我们不允许使用现有的 ORM(如果你想使用一个,你必须自己编写代码)并且只是为了教育自己,我认为同类像 Django 中那样的 ORM 会很好。

在 ORM 中,我不想使用与在 Django 中实现的样式相同的样式定义模型。即。

class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

Django 使用元类,在我的项目中我也在使用,但我对元类构造而不是实例这一事实有疑问,因此所有属性都是类属性并在所有实例之间共享。

这是我尝试过的通用示例,但由于我之前所说的,它不起作用:

def getmethod(attrname):
def _getmethod(self):
return getattr(self, "__"+attrname).get()
return _getmethod

def setmethod(attrname):
def _setmethod(self, value):
return getattr(self, "__"+attrname).set(value)
return _setmethod

class Metaclass(type):
def __new__(cls, name, based, attrs):
ndict = {}
for attr in attrs:
if isinstance(attrs[attr], Field):
ndict['__'+attr] = attrs[attr]
ndict[attr] = property(getmethod(attr), setmethod(attr))
return super(Metaclass, cls).__new__(cls, name, based, ndict)


class Field:
def __init__(self):
self.value = 0;

def set(self, value):
self.value = value

def get(self):
return self.value

class Mainclass:
__metaclass__ = Metaclass

class Childclass(Mainclass):
attr1 = Field()
attr2 = Field()


a = Childclass()
print "a, should be 0:", a.attr1
a.attr1 = "test"
print "a, should be test:", a.attr1

b = Childclass()

print "b, should be 0:", b.attr1

我试图从 Djangos 源代码中查找,但它太复杂了,我无法理解,而且“魔法”似乎隐藏在某处。

问题很简单,Django 如何在非常简单的示例中做到这一点?

最佳答案

一旦您检查了正确的代码,答案真的很简单。 Django 使用的元类将所有字段添加到 <model>._meta.fields (好吧,有点),但是 field 属性从实际类中删除了。唯一的异常(exception)是 RelatedField子类,在这种情况下会添加一个对象描述符(类似于一个属性——实际上,一个属性是一个对象描述符,只是带有一个本地实现)。

然后,在 __init__模型的方法,代码遍历所有字段,并在 *args 中设置提供的值或 **kwargs ,或者在实例上设置一个默认值

在您的示例中,这意味着类 Person永远不会有名为 first_name 的属性和 last_name , 但两个字段都存储在 Person._meta.fields 中.但是,Person 的实例将始终具有名为 first_name 的属性和 last_name ,即使它们没有作为参数提供。

关于python - 如何做类似 Django 模型的元类技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27989177/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com