gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 14:31:51 26 4
gpt4 key购买 nike

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

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

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

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 的回答似乎更加优雅和 self 记录,但这更加简洁。两者都不是完美的(相比之下,Django 的外键使用字符串名称的解决方案)——选择你的毒药。

恕我直言,最好为接口(interface)指定一个带点的名称而不是标识符。如果您觉得这种方法有用,您可以很容易地创建 schema.Object 的子类以供您自己使用。

关于python - 使用 zope.schema 定义循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9417571/

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