内部类 - 继承和覆盖其属性

问题描述 投票:4回答:1

我试图理解Django如何将python的元类用于它的数据库模型(选项),并提出了下面的简化代码片段,它应该大致模仿Django的逻辑。

class DatabaseOptions(object):

    def __init__(self, opts):
        if opts:
            for key, val in opts.__dict__.items():
                if not key.startswith('__') and not callable(val):
                    setattr(self, key, val)


class MetaModel(type):

    def __new__(cls, name, bases, classdict):
        result = super().__new__(cls, name, bases, dict(classdict))

        opts = classdict.pop('DbMeta', None)
        if opts:
            setattr(result, '_db_meta', DatabaseOptions(opts))

        return result


class Model(object, metaclass=MetaModel):

    class DbMeta:
        database = 'default'
        migrate = True


class User(Model):

    class DbMeta(Model.DbMeta):
        database = 'user'


class GroupUser(User):

    class DbMeta(User.DbMeta):
        database = 'group_user'

使用上面的代码,我希望以下输出:

print(Model._db_meta.database)  # default
print(Model._db_meta.migrate)  # True

print(User._db_meta.database)  # user
print(User._db_meta.migrate)   # True

print(GroupUser._db_meta.database)  # group_user
print(GroupUser._db_meta.migrate)  # True

相反,我得到以下异常

>>> python3 test.py 
default
True
user
Traceback (most recent call last):
  File "test.py", line 48, in <module>
    print(User._db_meta.migrate)   # True
AttributeError: 'DatabaseOptions' object has no attribute 'migrate'

我的问题是为什么User.DbMeta不继承migrateModel.DbMeta属性?这种问题有什么解决方案吗?

编辑:

根据丹尼尔的回答,我提出了以下对我有用的方法:

class DatabaseOptions(object):

    def __init__(self, opts):
        if opts:
            for key in dir(opts):
                if not key.startswith('__'):
                    val = getattr(opts, key, None)
                    if not callable(val):
                        setattr(self, key, val)
python django python-3.x django-models
1个回答
1
投票

这不是一个关于内部类的问题。

类属性就是类本身的属性。因此,__dict__Model.DbMeta包含“database”和“migrate”,但User.DbMeta中的dir()只包含“database”,因为这是该类定义的唯一属性。

但是,这些属性由__dict__显示;你应该迭代在DatabaseOptions而不是qazxswpoi上调用它的结果。

© www.soinside.com 2019 - 2024. All rights reserved.