使用元类在python中的每个其他类中导入模块

时间:2014-09-04 16:31:41

标签: python django metaclass

我需要创建一个业务查询模型,其中我需要创建一个循环依赖项,我使用的是一个类似django模型的设计来实现它,

#Modeule a.py

import b
class A:
    b_obj = B()
    a_property_1 = ObjectAttribute(b_obj.b_property_1) # a_property_1 is dependent on b_property_1
    a_property_2 = ObjectAttribute(b_obj.b_property_2)


#Module b.py

import a
class B:
        a_obj = A()
        b_property_1 = ObjectAttribute(a_obj.a_property_1)
        b_property_2 = ObjectAttribute(a_obj.a_property_2)

当我执行上面的程序时,它会抛出一个错误,在执行a.py时没有定义名字'B',反之亦然。

在那之后,我做了一些研究,以找出并找出已经通过ForeignKey实现类似的django模型

https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

我只需要实现我的ForeignKey模块,有人可以帮助我理解逻辑并以下面的格式编写代码。

#Modeule a.py

import b
class A:
    b_obj = MyForeignKey('B')
    a_property_1 = ObjectAttribute(b_obj.b_property_1) # a_property_1 is dependent on b_property_1
    a_property_2 = ObjectAttribute(b_obj.b_property_2)


#Module b.py

import a
class B:
        a_obj = MyForeignKey('A')
        b_property_1 = ObjectAttribute(a_obj.a_property_1)
        b_property_2 = ObjectAttribute(a_obj.a_property_2)

1 个答案:

答案 0 :(得分:0)

有一些方法可以做到这一点。其中一个是将您的外键作为实现类的代理类,在实例化时,只注释类模型,然后下一个属性访问实例化代理类,并保持其引用,后续属性只会被重定向到基础类。

允许在属性fecth上执行此类挂钩的一种机制(在Pyhton中记住一个类“方法”只是一个可调用的属性 - 所以它也适用于方法),是实现__getattribute__方法。

让我们假设你有一个“模型”模块(或其他类型的注册表),所有模型都被引用,创建后 - 你的代码看起来或多或少是这样的:

import models

class MyForeignKey(objec):
    def __init__(self, model_name, *args, **kw):
        self._model_name = model_name
        self._args = args
        self._kw = kw

    def _instantiate(self):
        self._object = getattr(models, self._model_name)(*self._args, **self._kw)

    def __getattribute__(self, attr):
        if attr in ("_model_name", "_args", "_kw", "_object", "_instantiate"):
            return object.__getattribute__(self, attr)
        if not hasattr(self, "_object"):
            self._instantiate()
        return getattr(self._object, attr)

    def __setattr__(self, attr, value):
        if attr in ("_model_name", "_args", "_kw", "_object"):
            return object.__setattr__(self, attr, value)
        if not hasattr(self, "_object"):
            self._instantiate()
        return setattr(self._object, attr, value)

请注意,(a)你的模型必须像我在问题中注释的那样继承“对象”,并且(b) - 如果你实现“dunder”方法(python双下划线方法)来覆盖任何行为,那么这是完整的模型 - 在这种情况下,你必须设置适当的te dunder方法来进行代理。