python - 在 Python 中自动管理数据库中的双向引用
问题描述
我有一个 ZODB 数据库,其中包含彼此具有双向链接的对象。这些通常是多对一和一对多的链接,即组和成员。成员具有对其所属组的引用,并且组具有对其成员的引用列表。
我正在寻找一种方法来自动确保双向引用是一致的。例如,如果组memberA
从 更改groupA
为groupB
,memberA
则应自动从成员列表中删除groupA
并添加到 列表中groupB
。
下面的代码是一种方法。
class Group:
def __init__(self, name):
self.name = name
self.members = []
self.db_ref = None
def add_member(self, member, cascade=True):
self.members.append(member)
if cascade:
self.db_ref.member_of_group_changed(self, member)
def remove_member(self, member, cascade=True):
self.members.remove(member)
if cascade:
self.db_ref.member_of_group_changed(self, member)
def __str__(self):
return self.__class__.__name__ + '("' + self.name + '")'
class Member:
def __init__(self, name):
self.name = name
self.group = None
self.db_ref = None
def set_group(self, group, cascade=True):
old_group = self.group
self.group = group
if cascade:
self.db_ref.group_of_member_changed(self, old_group)
def __str__(self):
return self.__class__.__name__ + '("' + self.name + '")'
def __repr__(self):
return self.__str__()
class Database:
def __init__(self):
self.groups = []
self.members = []
def add_item(self, item):
item.db_ref = self
if type(item) is Group:
self.groups.append(item)
elif type(item) is Member:
self.members.append(item)
def group_of_member_changed(self, member, old_group):
if not old_group is None: # group unset
old_group.remove_member(member, cascade=False)
elif not member.group is None: # group set
member.group.add_member(member, cascade=False)
def member_of_group_changed(self, group, member):
if member in group.members: # member added to group
member.set_group(group, cascade=False)
else: # member removed from group
member.set_group(None, cascade=False)
db = Database()
groupA = Group("groupA")
memberA = Member("memberA")
memberB = Member("memberB")
db.add_item(groupA)
db.add_item(memberA)
db.add_item(memberB)
# add memberA to groupA
groupA.add_member(memberA)
print(groupA.members) # [Member("memberA")]
print(memberA.group) # Group("groupA")
# set group of memberB to groupA
memberB.set_group(groupA)
print(memberB.group) # Group("groupA")
print(groupA.members) # [Member("memberA"), Member("memberB")]
# remove memberB from groupA
groupA.remove_member(memberB)
print(groupA.members) # [Member("memberA")]
print(memberB.group) # None
# unset group of memberA
memberA.set_group(None)
print(memberA.group) # None
print(groupA.members) # []
但是,感觉有点笨拙。我怀疑有更好的方法,因为我想这种情况经常发生。如果不需要定义类似的方法,set_group()
或者add_member()
可以修改 setter 和 append 函数,那就太好了,即:
groupA.members.append(memberA) # also sets sets memberA.group to groupA
memberB.group = groupA # also adds memberB to groupA.members
Database
在提供的代码示例中,我更喜欢通过类处理更新引用。比如for memberB.group = groupA
,setter方法设置memberB.group
为groupA
,不应该直接调用append
添加memberB
到的方法groupA
。数据库应该这样做。
我查看了描述符。我猜这个函数 __set__()
可以替代set_group()
,但这不是add_member()
/的选项remove_member()
。
如果可以在将对象添加到数据库时动态添加此行为,那将是非常酷的。但也许我变得贪婪:)。
解决方案
推荐阅读
- jsp - 使用 JsPDF 和 JSP 在服务器上存储生成的 PDF 文件
- python - 迁移学习神经网络不学习
- python - Selenium 获取所有行
- mysql - 带有大数据的 SELECT 查询中的 MYSQL SELECT:请求超时
- javascript - Firebase web v9 升级中断 react-firebase-hooks “useCollectionData()”
- html - 带有按钮的图像如何保持原位(响应性)?
- javascript - 上传文件到其他服务时如何获取上传进度?
- reactjs - 在初始安装时反应 useEffect 防止
- reactjs - 在聊天项目中动态更新 React 组件的问题
- r - 在 Windows 上检测中文字符时出现 str_detect() 错误