私は次のことをしようとしています。インスタンスを相互に参照する2つのクラスを定義します。ユーザーは複数のグループに属し、グループには複数のユーザーが含まれます。実際のデータはデータベースに格納されており、そこには外部キーを使用する多対多関係の単純な問題があります。全く問題なし。zope.schemaを使って循環参照を定義する
その後、データはORMによってロードされ、Pythonオブジェクトのインスタンスに格納されます。 ORMが(SQLAlchemy)使用されているようにバックグラウンドを管理しても、何の問題もありません。
ここで、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が異なるソースファイルで定義され、IGroupの一部がIUserを定義するファイルで定義されているため、IUserの定義後にIGroupの定義を完了するための回避策が見つかりましたが、それはまったく満足できません。
zope.schemaを使用して適切な方法がありますか?
私のコメントでは、Martijnの答えは実際には全く働いていないと確信しています(私の回避策はうまくいきません)。私はあなたのことが分かりません。理論的根拠:私が理解しているように、IBarは定義時にIFooのフィールドのコピーを使用して定義されているため、後でIFooを変更すると埋め込みIFooは変更されません。しかし、私はそれが本当に分かりません... – kriss
はい、Pythonの元のクラスはここにサルでパッチが当てられています。したがって、インターフェイスモジュールをインポートした後のランタイム中のIFooのすべてのコンシューマは、検証とイントロスペクションのためのスキーマ。この手法は、一貫した成功を収めた複数のプロダクションプロジェクトで使用されています。 – sdupton