我有一个python模块,我多年来一直用它来处理一系列文本文件以便工作。我现在需要在db中存储一些信息(使用SQLAlchemy),但我仍然希望在没有db支持的情况下使用模块的灵活性,即不必实际使用sqlalchemy import(或已安装)。截至目前,我有以下内容......我一直在创建Product
或DBProduct
等等,这取决于我是否打算使用数据库。
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Product(object):
pass
class WebSession(Product):
pass
class Malware(WebSession):
pass
class DBProduct(Product, Base):
pass
class DBWebSession(WebSession, DBProduct):
pass
class DBMalware(Malware, DBWebSession):
pass
然而,我觉得必须有一个更简单/更清洁的方法来做到这一点。我觉得我正在创造遗产混乱和潜在的问题。理想情况下,我想创建一个Product
,WebSession
等类(可能使用装饰器),其中包含使用数据库所需的信息,但它只在调用类似的东西后启用/运行enable_db_support()
。一旦调用了该函数,那么无论我创建什么对象,它本身(以及它继承的所有对象)都会启用所有列
绑定等。我还应该注意,如果我以某种方式弄清楚如何在一个类中包含Product
和DBProduct
,我有时需要同一个函数的两个版本:1如果db支持是启用,如果不是,则启用1。我在调用enable_db_support()
时也考虑过“重新创建”对象层次结构,但这也是一场噩梦。
感谢任何帮助。
答案 0 :(得分:0)
在我看来,DRYest要做的就是抽象出数据存储格式的细节,无论是纯文本文件还是数据库。
也就是说,编写其他代码用来存储数据的某种抽象层,并使其成为可以在SQL或文本之间切换抽象层的输出。
或者换句话说,不要写一个Product
和DB_Product
类。而是编写一个store_data()
函数,可以告诉他使用format='text'
或format='db'
。然后在任何地方使用它。
这实际上是SQLAlchemy在幕后所做的事情 - 您不必为SQLAlchemy编写单独的代码,具体取决于它是否正在驱动mySQL,PostgreSQL等。这些都是在SQLAlchemy中处理的,并且您使用了抽象的(数据库中立的接口。
或者,如果您对SQLAlchemy
的反对意见是它不是Python内置的,那么总是sqlite3
。这为您提供了一个没有胖的SQL关系数据库的所有优点。
或者,交替使用sqlite3
作为中间格式。因此,重写所有您的代码以使用sqlite3
,然后根据需要从sqlite3
转换为纯文本(或其他数据库)。在极限情况下,转换为纯文本只是sqlite3 db .dump
away.
答案 1 :(得分:0)
好吧,您可以使用Classical Mapping创建纯粹的非数据库感知模型而不使用declarative
扩展名。但是,在这种情况下,您将无法在SA中使用relationships
,但对于简单的数据导入/导出类型的模型,这应该足够了:
# models.py
class User(object):
pass
----
# mappings.py
from sqlalchemy import Table, MetaData, Column, ForeignKey, Integer, String
from sqlalchemy.orm import mapper
from models import User
metadata = MetaData()
user = Table('user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('password', String(12))
)
mapper(User, user)
另一个选择是为某个其他模块中定义的模型创建一个基类,并在启动时使用configure
这个基类是否支持DB,如果是DB-aware版本添加关系和引擎配置等附加功能......