编程语言
首页 > 编程语言> > python – 使用zope.schema定义循环引用

python – 使用zope.schema定义循环引用

作者:互联网

我正在尝试执行以下操作,定义两个实例相互引用的类,如以下示例中的“用户和组”.用户可以属于多个组,组可以包含多个用户.实际数据存储在数据库中,这是使用外键的多对多关系的简单问题.没问题.

之后,数据通过ORM加载并存储在python对象的实例中.使用的ORM(SQLAlchemy)管理backrefs仍然没有问题.

现在我想检查python对象是否符合使用zope.interface和zope.schema的某些接口.这就是我遇到麻烦的地方.

import zope.schema as schema
from zope.interface import Interface, implements

class IGroup(Interface):
    name = schema.TextLine(title=u"Group's name")
#    user_list = schema.List(title = u"List of Users in this group", value_type = sz.Object(IUser))

class IUser(Interface):
    name = schema.TextLine(title=u"User's name")
    group_list = schema.List(title = u"List of Groups containing that user",
        value_type = schema.Object(IGroup))

IGroup._InterfaceClass__attrs['user_list'] = zs.List(title = u"List of Users in this group", required = False, value_type = zs.Object(IUser))

class Group(object):
    implements(IGroup)

    def __init__(self, name):
        self.name = name
        self.user_list = []

class User(object):
    implements(IUser)

    def __init__(self, name):
        self.name = name
        self.group_list = []

alice = User(u'Alice')
bob = User(u'Bob')
chuck = User(u'Chuck')
group_users = Group(u"Users")
group_auditors = Group(u"Auditors")
group_administrators = Group(u"Administrators")

def add_user_in_group(user, group):
    user.group_list.append(group)
    group.user_list.append(user)

add_user_in_group(alice, group_users)
add_user_in_group(bob, group_users)
add_user_in_group(chuck, group_users)
add_user_in_group(chuck, group_auditors)
add_user_in_group(chuck, group_administrators)

for x in [alice, bob, chuck]:
    errors = schema.getValidationErrors(IUser, x)
    if errors: print errors
    print "User ", x.name, " is in groups ", [y.name for y in x.group_list]

for x in [group_users, group_auditors, group_administrators]:
    errors = schema.getValidationErrors(IGroup, x)
    if errors: print errors
    print "Group ", x.name, " contains users ", [y.name for y in x.user_list]

我的问题是注释行.我无法使用IUser定义IGroup,因为那时IUser尚未定义.在IUser的定义之后,我找到了一个完成IGroup定义的解决方法但是根本不满意,因为IUser和IGroup在不同的源文件中定义,而IGroup的一部分在定义IUser的文件中定义.

有没有正确的方法来使用zope.schema?

解决方法:

定义后修改字段:

#imports elided

class IFoo(Interface):
    bar = schema.Object(schema=Interface)

class IBar(Interface):
    foo = schema.Object(schema=IFoo)

IFoo['bar'].schema = IBar

Martijn的答案似乎更优雅,更自我记录,但这更简洁.两者都不完美(相比之下,Django的解决方案是使用外键的字符串名称) – 选择你的毒药.

恕我直言,为界面指定一个虚线名称而不是标识符会很好.如果您发现该方法有用,您可以非常轻松地为此创建一个schema.Object的子类供您自己使用.

标签:circular-reference,python,zope-interface
来源: https://codeday.me/bug/20190902/1790943.html