是否有可能在SQLAlchemy中将列标记为do-not-pickle,以便在取消对其进行unickled后从数据库中按需加载?
这可以通过 <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<div class="clickMe">
</div>
列部分实现,但如果随后加载了该列,它也会被腌制。
(由于内置的deferred
具有不可挽回的特性,因此看起来在Python2.7中仍然存在使用酸洗Geoalchemy2 Geometry列的问题:{{3} })
答案 0 :(得分:0)
这是一个天真的__getstate__
实施,但不会有效,但有希望提示正确答案:
Base = declarative_base(metadata=route_metadata)
cols_to_omit = ['my_col_1']
class MyClass(Base):
my_col_0 = Column(Integer)
my_col_1 = Column(Integer)
def __getstate__(self):
return dict((c, getattr(self, c)) for c in \
self.__table__.columns.keys() \
if c not in cols_to_omit)
def __setstate__(self, *args):
for c, v in args[0].items():
setattr(self, c, v)
from pickle import *
pp = dumps(MyClass.query.first())
obj = loads(pp)
这会给AttributeError: 'MyClass' object has no attribute '_sa_instance_state'
答案 1 :(得分:0)
这有点牵扯,因为你不能阻止对某个列进行腌制,因为控制延迟加载的内容实际上在_sa_instance_state
属性中,所以即使你没有腌制实例字典中的某些属性SQLAlchemy不知道这意味着它已过期。
一个(稍微hacky)解决方案是在你unpickle时使属性失效:
class Foo(Base):
__tablename__ = "foo"
id = Column(Integer, primary_key=True)
foo = Column(String)
bar = Column(String)
def __getstate__(self):
return {k: v for k, v in self.__dict__.items() if k != "bar"}
def __setstate__(self, d):
for k, v in d.items():
self.__dict__[k] = v
self._sa_instance_state._expire_attributes(self.__dict__, ("bar",))
请注意,unpickling的结果是一个分离的实例,因此您需要小心使用它:
foo = session.query(Foo).first()
foo = pickle.loads(pickle.dumps(foo))
print(foo.foo) # fine
# print(foo.bar) # sqlalchemy.orm.exc.DetachedInstanceError
foo = session.merge(foo, load=False)
print(foo.foo) # no query
print(foo.bar) # causes a query