我想为给定的SQLAlchemy映射类重写__deepcopy__
,以便它忽略任何SQLA属性,但深入复制该类的其他所有内容。
我并不是特别熟悉覆盖任何Python的内置对象,但我对我想要的东西有所了解。
让我们创建一个使用SQLA映射的非常简单的类User
。
class User(object):
def __init__(self, user_id=None, name=None):
self.user_id = user_id
self.name = name
我已经使用dir()
来查看映射之前和之后的SQLAlchemy特定属性,并且我找到了_sa_class_manager
和_sa_instance_state
。
Questions
只要那些是唯一的,在定义__deepcopy__
时我会如何忽略它?
此外,SQLA是否有任何属性注入映射对象?
(我在之前的一个问题中问过这个问题(在我选择主要问题的答案后几天作为编辑),但我想我错过了那里的火车。为此道歉。)
<小时/>
Edit - Fixed code thanks to zifot's answer
我从Python文档中得到的唯一一点就是你需要定义带有memo
的深度复制作为额外的参数。经过几十年的挖掘后,我尝试了这个:
def __deepcopy__(self, memo):
dpcpy = self.__class__()
memo[id(self)] = dpcpy
for attr in dir(self):
if not attr.startswith('_'):
value = getattr(self, attr)
setattr(dpcpy, attr, copy.deepcopy(value, memo))
return dpcpy
然后我创建了User
的实例:
snake = User(913, 'Snake,S.')
之后,我尝试了deepcopy
操作:
snake_dc = copy.deepcopy(snake)
...而snake_dc
仍然包含SQLA属性......
我愿意提供帮助,建议等等。
答案 0 :(得分:1)
mavnn is right。例如,尝试将用户的init更改为:
def __init__(self, user_id = None, name = None):
self.user_id = user_id
self.name = name
至于复制映射的实例,我建议阅读this thread
答案 1 :(得分:1)
当(深度)复制时,您不应该拨打__init__
而是拨打__new__
。
一个例子:
def __copy__(self):
cls = self.__class__
newobject = cls.__new__(cls)
newobject.__dict__.update(self.__dict__)
return newobject
答案 2 :(得分:0)
我不是深度复制方面的专家,但从错误看起来你需要一个无参数构造函数来调用self.__class__()
而不带参数。
答案 3 :(得分:0)
要排除sqlalchemy列和映射属性,您可以执行以下操作:
for attr in dir(self):
if not self._sa_class_manager.mapper.has_property(key):
...