- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个我根本无法解决的奇怪问题。本质上,我有一个可以完美运行的模型和系统 - 除了在一组非常特定(并且看似任意)的情况下。
我会在一秒钟内粘贴模型,但这是我的想法。我希望对某些表进行版本控制。这意味着对于一个给定的表,我将它分成两个表,Master 部分包含对象的自然键,Version 表包含所有可能更改的关联数据。然后我的一些模型当然有关系,所以我创建了一个链接版本的连接表。
模型如下:
class Versioned(object):
def __init__(self, **kwargs):
super(Versioned, self).__init__(**kwargs)
self.active = True
self.created_on = datetime.datetime.now()
active = Column(BOOLEAN)
created_on = Column(TIMESTAMP, server_default=func.now())
def __eq__(self, other):
return self.__class__ == other.__class__ and \
all([getattr(self, key) == getattr(other, key)
for key in self.comparison_keys
])
def __ne__(self, other):
return not self.__eq__(other)
comparison_keys = []
class Parent(Base):
__tablename__ = 'parent'
id = Column(INTEGER, primary_key=True)
name = Column(TEXT)
versions = relationship("ParentVersion", back_populates="master")
children = relationship("Child", back_populates="parent")
@property
def current_version(self):
active_versions = [v for v in self.versions if v.active==True]
return active_versions[0] if active_versions else None
class ParentVersion(Versioned, Base):
__tablename__ = 'parent_version'
id = Column(INTEGER, primary_key=True)
master_id = Column(INTEGER, ForeignKey(Parent.id))
address = Column(TEXT)
master = relationship("Parent", back_populates="versions")
children = relationship("ChildVersion",
secondary=lambda : Parent_Child.__table__
)
class Child(Base):
__tablename__ = 'child'
id = Column(INTEGER, primary_key=True)
parent_id = Column(INTEGER, ForeignKey(Parent.id))
name = Column(TEXT)
versions = relationship("ChildVersion", back_populates="master")
parent = relationship("Parent", back_populates="children")
@property
def current_version(self):
active_versions = [v for v in self.versions if v.active==True]
return active_versions[0] if active_versions else None
class ChildVersion(Versioned, Base):
__tablename__ = 'child_version'
id = Column(INTEGER, primary_key=True)
master_id = Column(INTEGER, ForeignKey(Child.id))
age = Column(INTEGER)
fav_toy = Column(TEXT)
master = relationship("Child", back_populates="versions")
parents = relationship("ParentVersion",
secondary=lambda: Parent_Child.__table__,
)
comparison_keys = [
'age',
'fav_toy',
]
class Parent_Child(Base):
__tablename__ = 'parent_child'
id = Column(INTEGER, primary_key=True)
parent_id = Column(INTEGER, ForeignKey(ParentVersion.id))
child_id = Column(INTEGER, ForeignKey(ChildVersion.id))
好的,所以我知道最近的 SQLAlchemy 模型有一些版本控制的想法,可能我做错了。但这非常适合我的用例。所以幽默一下,让我们假设模型没问题(在一般意义上 - 如果有一个小细节导致了可以很好修复的错误)
现在假设我要插入数据。我有来自某个来源的数据,我接受它并构建模型。即,将事物拆分为 Master/Version,分配子关系,分配版本关系。现在我想将它与我数据库中已有的数据进行比较。对于每个主对象,如果我找到它,我会比较版本。如果版本不同,则创建一个新版本。棘手的部分变成了,如果子版本不同,我想插入一个新的父版本,并更新它的所有关系。也许代码解释这部分更有意义。 search_parent
是我在预解析阶段创建的对象。它有一个版本,子对象也有版本。
parent_conds = [
getattr(search_parent.__class__, name) == getattr(search_parent, name)
for name, column in search_parent.__class__.__mapper__.columns.items()
if not column.primary_key
]
parent_match = session.query(Parent).filter(*parent_conds).first()
# We are going to make a new version
parent_match.current_version.active=False
parent_match.versions.append(search_parent.current_version)
for search_child in search_parent.children[:]:
search_child.parent_id = parent_match.id
search_conds = [
getattr(search_child.__class__, name) == getattr(search_child, name)
for name, column in search_child.__class__.__mapper__.columns.items()
if not column.primary_key
]
child_match = session.query(Child).filter(*search_conds).first()
if child_match.current_version != search_child.current_version:
# create a new version: deactivate the old one, insert the new
child_match.current_version.active=False
child_match.versions.append(search_child.current_version)
else:
# copy the old version to point to the new parent version
children = parent_match.current_version.children
children.append(child_match.current_version)
children.remove(search_child.current_version)
session.expunge(search_child.current_version)
session.expunge(search_child)
session.expunge(search_parent)
session.add(parent_match)
session.commit()
好吧,再说一次,这可能不是完美的,甚至不是最好的方法。但它确实有效。除了,这是我无法弄清楚的。如果我将 child 的年龄属性更新为整数值零,则它不起作用。如果子对象从 0 岁开始,而我将其更改为其他对象,则效果很好。如果我从某个非零整数开始,并将年龄更新为 0,我会收到此警告:
SAWarning: Object of type <ChildVersion> not in session, add operation along 'ParentVersion.children' won't proceed (mapperutil.state_class_str(child), operation, self.prop))
已插入更新版本,但不会插入到 parent_child 连接表中。并不是它失败了,而是 SQLAlchemy 已经确定子对象不存在并且无法创建连接。但它确实存在,我知道它被插入了。
同样,只有当我插入一个 age=0 的新版本时才会发生这种情况。如果我要插入任何其他年龄段的新版本,这完全符合我的要求。
关于这个错误还有其他奇怪的事情 - 如果你没有插入足够多的 child 它就不会发生(似乎是大约 12 个触发错误),它有时不会发生取决于其他属性。我不认为我完全理解导致它的表面区域。
感谢您花时间阅读到这里。我有一个完整的工作演示,其中包含我很乐意分享的源数据,它只需要一些设置,所以我不知道它是否适合在这篇文章中使用。我希望有人知道要看什么,因为在这一点上我完全出局了。
编辑:这是导致警告的完整堆栈跟踪。
File "repro.py", line 313, in <module>
load_data(session, second_run)
File "repro.py", line 293, in load_data
session.commit()
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 801, in commit
self.transaction.commit()
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 392, in commit
self._prepare_impl()
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl
self.session.flush()
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2019, in flush
self._flush(objects)
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2101, in _flush
flush_context.execute()
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 373, in execute
rec.execute(self)
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 487, in execute
self.dependency_processor.process_saves(uow, states)
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 1053, in process_saves
False, uowcommit, "add"):
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 1154, in _synchronize
(mapperutil.state_class_str(child), operation, self.prop))
File "/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 1297, in warn
warnings.warn(msg, exc.SAWarning, stacklevel=2)
File "repro.py", line 10, in warn_with_traceback
traceback.print_stack()
/Users/me/virtualenvs/dev/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py:1154: SAWarning: Object of type <ChildVersion> not in session, add operation along 'ParentVersion.children' won't proceed
(mapperutil.state_class_str(child), operation, self.prop))
编辑2:这是一个带有 python 文件的要点,您可以运行它来查看奇怪的行为。 https://gist.github.com/jbouricius/2ede420fb1f7a2deec9f557c76ced7f9
最佳答案
出现此错误的原因是您无意中将对象添加到 session 中。
这是 MVCE:
engine = create_engine("sqlite://", echo=False)
def get_data():
children = [
Child(name="Carol", versions=[ChildVersion(age=0, fav_toy="med")]),
Child(name="Timmy", versions=[ChildVersion(age=0, fav_toy="med")]),
]
return Parent(
name="Zane", children=children,
versions=[
ParentVersion(
address="123 Fake St",
children=[v for child in children for v in child.versions]
)
]
)
def main():
Base.metadata.create_all(engine)
session = Session(engine)
parent_match = get_data()
session.add(parent_match)
session.commit()
with session.no_autoflush:
search_parent = get_data()
parent_match.versions.append(search_parent.current_version)
for search_child in search_parent.children[:]:
child_match = next(c for c in parent_match.children if c.name == search_child.name)
if child_match.current_version != search_child.current_version:
child_match.versions.append(search_child.current_version)
else:
session.expunge(search_child.current_version)
session.expunge(search_child)
session.expunge(search_parent)
session.commit()
另外:这是您需要在问题本身中提供的内容。提供带有说明的 tarball 并不是获得答案的最佳方式。
线
parent_match.versions.append(search_parent.current_version)
不仅添加了search_parent.current_version
,还添加了search_parent
,后者又添加了所有相关对象,包括其他的子版本 children 。从您后来删除其他相关对象以防止将它们添加到 session 中这一事实来看,我得出结论,您只想添加 search_parent.current_version
而没有添加其他相关对象。由于关系的循环性质,在添加它们之前,您需要注意只从 search_parent
中提取您想要的对象。这是固定的 MVCE:
with session.no_autoflush:
search_parent = get_data()
current_parent_version = search_parent.current_version
search_parent.versions.remove(current_parent_version)
current_parent_version.children = [] # <--- this is key
for search_child in search_parent.children[:]:
child_match = next(c for c in parent_match.children if c.name == search_child.name)
if child_match.current_version != search_child.current_version:
current_child_version = search_child.current_version
search_child.versions.remove(current_child_version)
child_match.versions.append(current_child_version)
current_parent_version.children.append(current_child_version)
parent_match.versions.append(current_parent_version)
session.commit()
关于python-2.7 - SQLAlchemy 辅助连接模型在奇怪的情况下失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39298822/
我知道这个问题可能已经被问过,但我检查了所有这些,我认为我的情况有所不同(请友善)。所以我有两个数据集,第一个是测试数据集,第二个是我保存在数据框中的预测(预测值,这就是没有数据列的原因)。我想合并两
在 .loc 方法的帮助下,我根据同一数据框中另一列中的值来识别 Panda 数据框中某一列中的值。 下面给出了代码片段供您引用: var1 = output_df['Player'].loc[out
当我在 Windows 中使用 WinSCP 通过 Ubuntu 连接到 VMware 时,它提示: The server rejected SFTP connection, but it lis
我正在开发一个使用 xml web 服务的 android 应用程序。在 wi-fi 网络中连接时工作正常,但在 3G 网络中连接时失败(未找到 http 404)。 这不仅仅发生在设备中。为了进行测
我有一个XIB包含我的控件的文件,加载到 Interface Builder(Snow Leopard 上的 Xcode 4.0.2)中。 文件的所有者被设置为 someClassController
我在本地计算机上管理 MySQL 数据库,并通过运行以下程序通过 C 连接到它: #include #include #include int main(int argc, char** arg
我不知道为什么每次有人访问我网站上的页面时,都会打开一个与数据库的新连接。最终我到达了大约 300 并收到错误并且页面不再加载。我认为它应该工作的方式是,我将 maxIdle 设置为 30,这意味着
希望清理 NMEA GPS 中的 .txt 文件。我当前的代码如下。 deletes = ['$GPGGA', '$GPGSA', '$GPGSV', '$PSRF156', ] searchquer
我有一个 URL、一个用户名和一个密码。我想在 C# .Net WinForms 中建立 VPN 连接。 你能告诉我从哪里开始吗?任何第三方 API? 代码示例将受到高度赞赏... 最佳答案 您可以像
有没有更好的方法将字符串 vector 转换为字符 vector ,字符串之间的终止符为零。 因此,如果我有一个包含以下字符串的 vector "test","my","string",那么我想接收一
我正在编写一个库,它不断检查 android 设备的连接,并在设备连接、断开连接或互联网连接变慢时给出回调。 https://github.com/muddassir235/connection_ch
我的操作系统:Centos 7 + CLOUDLINUX 7.7当我尝试从服务器登录Mysql时 [root@server3 ~]# Mysql -u root -h localhost -P 330
我收到错误:Puma 发现此错误:无法打开到本地主机的 TCP 连接:9200(连接被拒绝 - 连接(2)用于“本地主机”端口 9200)(Faraday::ConnectionFailed)在我的
请给我一些解决以下错误的方法。 这是一个聊天应用....代码和错误如下:: conversations_controller.rb def create if Conversation.bet
我想将两个单元格中的数据连接到一个单元格中。我还想只组合那些具有相同 ID 的单元格。 任务 ID 名称 4355.2 参与者 4355.2 领袖 4462.1 在线 4462.1 快速 4597.1
我经常需要连接 TSQL 中的字段... 使用“+”运算符时 TSQL 强制您处理的两个问题是 Data Type Precedence和 NULL 值。 使用数据类型优先级,问题是转换错误。 1)
有没有在 iPad 或 iPhone 应用程序中使用 Facebook 连接。 这个想法是登录这个应用程序,然后能够看到我的哪些 facebook 用户也在使用该应用程序及其功能。 最佳答案 是的。
我在连接或打印字符串时遇到了一个奇怪的问题。我有一个 char * ,可以将其设置为字符串文字的几个值之一。 char *myStrLiteral = NULL; ... if(blah) myS
对于以下数据 - let $x := "Yahooooo !!!! Select one number - " let $y := 1 2 3 4 5 6 7 我想得到
我正在看 UDEMY for perl 的培训视频,但是视频不清晰,看起来有错误。 培训展示了如何使用以下示例连接 2 个字符串: #!usr/bin/perl print $str = "Hi";
我是一名优秀的程序员,十分优秀!