我们正在使用sqlalchemy的自动加载功能来进行列映射,以防止我们的代码中出现硬编码。
class users(Base):
__tablename__ = 'users'
__table_args__ = {
'autoload': True,
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
有没有办法序列化或缓存自动加载的元数据/ orms,所以每次我们需要从其他脚本/函数引用我们的orm类时,我们不必经历自动加载过程?
我看过烧杯缓存和泡菜,但是如果有可能或者怎么做的话,还没有找到明确的答案。
理想情况下,只有在我们提交了对数据库结构的更改但是从所有其他脚本/函数引用数据库映射的非自动加载/持久/缓存版本时,才运行自动加载映射脚本,
有什么想法吗?
答案 0 :(得分:6)
我现在正在做的是在通过数据库连接(MySQL)运行反射之后挑选元数据,并且一旦pickle可用,使用pickle元数据来反映具有绑定到SQLite引擎的元数据的模式。
cachefile='orm.p'
dbfile='database'
engine_dev = create_engine(#db connect, echo=True)
engine_meta = create_engine('sqlite:///%s' % dbfile,echo=True)
Base = declarative_base()
Base.metadata.bind = engine_dev
metadata = MetaData(bind=engine_dev)
# load from pickle
try:
with open(cachefile, 'r') as cache:
metadata2 = pickle.load(cache)
metadata2.bind = engine_meta
cache.close()
class Users(Base):
__table__ = Table('users', metadata2, autoload=True)
print "ORM loaded from pickle"
# if no pickle, use reflect through database connection
except:
class Users(Base):
__table__ = Table('users', metadata, autoload=True)
print "ORM through database autoload"
# create metapickle
metadata.create_all()
with open(cachefile, 'w') as cache:
pickle.dump(metadata, cache)
cache.close()
任何评论如果这是好的(它有效)或有什么我可以改进?
答案 1 :(得分:0)
我的解决方案与@ user1572502的解决方案并没有很大不同,但可能很有用。我将缓存的元数据文件放置在~/.sqlalchemy_cache
中,但是它们可以在任何地方。
# assuming something like this:
Base = declarative_base(bind=engine)
metadata_pickle_filename = "mydb_metadata_cache.pickle"
# ------------------------------------------
# Load the cached metadata if it's available
# ------------------------------------------
# NOTE: delete the cached file if the database schema changes!!
cache_path = os.path.join(os.path.expanduser("~"), ".sqlalchemy_cache")
cached_metadata = None
if os.path.exists(cache_path):
try:
with open(os.path.join(cache_path, metadata_pickle_filename), 'rb') as cache_file:
cached_metadata = pickle.load(file=cache_file)
except IOError:
# cache file not found - no problem
pass
# ------------------------------------------
# -----------------------------
# Define database table classes
# -----------------------------
class MyTable(Base):
if cached_metadata:
__table__ = cached_metadata.tables['my_schema.my_table']
else:
__tablename__ = 'my_table'
__table_args__ = {'autoload':True, 'schema':'my_schema'}
# ... continue for any other tables ...
# ----------------------------------------
# If no cached metadata was found, save it
# ----------------------------------------
if cached_metadata is None:
# cache the metadata for future loading
# - MUST DELETE IF THE DATABASE SCHEMA HAS CHANGED
try:
if not os.path.exists(cache_path):
os.makedirs(cache_path)
# make sure to open in binary mode - we're writing bytes, not str
with open(os.path.join(cache_path, metadata_pickle_filename), 'wb') as cache_file:
pickle.dump(Base.metadata, cache_file)
except:
# couldn't write the file for some reason
pass
重要说明!如果数据库架构发生更改,则必须删除缓存的文件以强制代码自动加载并创建新的缓存。如果您不这样做,更改将反映在代码中。这是一件容易忘记的事情。