改进的声明性sqlalchemy模型
SQLAlchemy-Unchained的Python项目详细描述
sqlalchemy未受限制
sqlalchemy的增强声明模型。
有用链接
用法
安装
需要python 3.5+、sqlalchemy和alembic(用于迁移)
$ pip install sqlalchemy-unchained
让我们创建一个目录结构来使用:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py
从现在开始,假设您是从项目的
目录工作的。代码示例顶部的所有文件路径都将与此目录相关,所有命令都应从此目录运行(除非另有说明)。
配置
使用sqlite
# your_package/config.pyimportosclassConfig:PROJECT_ROOT=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))DATABASE_URI='sqlite:///'+os.path.join(PROJECT_ROOT,'db','dev.sqlite')
在这里,我们将在project root/db/dev.sqlite
使用postgresql或mariadb/mysql
如果您想使用postgresql或mariadb/mysql,现在是配置它的时候了。例如,将postgresql与psycopg2
引擎一起使用:
# your_package/config.pyimportosclassConfig:DATABASE_URI='{engine}://{user}:{pw}@{host}:{port}/{db}'.format(engine=os.getenv('SQLALCHEMY_DATABASE_ENGINE','postgresql+psycopg2'),user=os.getenv('SQLALCHEMY_DATABASE_USER','your_db_user'),pw=os.getenv('SQLALCHEMY_DATABASE_PASSWORD','your_db_user_password'),host=os.getenv('SQLALCHEMY_DATABASE_HOST','127.0.0.1'),port=os.getenv('SQLALCHEMY_DATABASE_PORT',5432),db=os.getenv('SQLALCHEMY_DATABASE_NAME','your_db_name'))
对于mariadb/mysql,将引擎
参数替换为mysql+mysqldb
,将端口
参数替换为3306
请注意,您可能需要安装相关的驱动程序包,例如:
# for postgresql+psycopg2 pip install --no-binary psycopg2 # for mysql+mysqldb pip install mysqlclient
有关连接到其他数据库引擎的详细信息,请参阅sqlalchemy diactals上的官方文档。
连接
# your_package/db.pyfromsqlalchemy_unchainedimport*from.configimportConfigengine,Session,Model,relationship=init_sqlalchemy_unchained(Config.DATABASE_URI)
如果您需要自定义这些参数中的任何一个的创建,这就是init\u sqlalchemy\u unchained
在幕后所做的工作:
# your_package/db.pyfromsqlalchemy.ormimportrelationshipas_relationshipfromsqlalchemy_unchainedimport*fromsqlalchemy_unchainedimport_wrap_with_default_query_classfrom.configimportConfigengine=create_engine(Config.DATABASE_URI)Session=scoped_session_factory(bind=engine,query_cls=BaseQuery)SessionManager.set_session_factory(Session)Model=declarative_base(bind=engine)relationship=_wrap_with_default_query_class(_relationship,BaseQuery)
创建一些模型
# your_package/models.pyfrom.importdbclassParent(db.Model):name=db.Column(db.String,nullable=False)children=db.relationship('Child',back_populates='parent')classChild(db.Model):name=db.Column(db.String,nullable=False)parent_id=db.foreign_key('Parent',nullable=False)parent=db.relationship('Parent',back_populates='children')
这是与使用stock sqlalchemy真正不同的第一点。默认情况下,sqlalchemy中的模型会自动配置它们的\u tablename\uuu
,并包含一个主键列id
以及自动加时间戳的列在
处创建和在
处更新。
这是可定制的。例如,如果要重命名父级上的列并禁用子级上的时间戳:
# your_package/models.pyfrom.importdbclassParent(db.Model):classMeta:pk='pk'created_at='created'updated_at='updated'name=db.Column(db.String,nullable=False)children=db.relationship('Child',back_populates='parent')classChild(db.Model):classMeta:table='child'# explicitly set/customize the table namecreated_at=Noneupdated_at=Nonename=db.Column(db.String,nullable=False)parent_id=db.foreign_key('Parent',nullable=False)parent=db.relationship('Parent',back_populates='children')
还有sqlalchemy unchained支持的其他meta
选项,我们稍后将讨论这些选项。我们还将介绍如何更改所有模型的默认值,以及如何添加对您自己的自定义meta
选项的支持。但现在,让我们在继续之前配置迁移。
配置数据库迁移
初始化alembic:
$ pip install sqlalchemy-unchained0
接下来,我们需要将alembic配置为使用已经配置好的相同数据库。这发生在db/migrations/env.py
文件的顶部,该文件是为我们生成的alembic init db/migrations
命令。修改以下行:
$ pip install sqlalchemy-unchained1
为了使这些导入语句正常工作,我们需要安装我们的包。让我们创建一个最小的setup.py
$ pip install sqlalchemy-unchained2
并将我们的软件包安装到您用于开发的虚拟环境中:
$ pip install sqlalchemy-unchained3
这应该是迁移工作所需的全部。让我们为我们的模型生成一个迁移,并运行它:
$ pip install sqlalchemy-unchained4
使用SessionManager和模型管理器
sqlalchemy uncheed鼓励采用sqlalchemy使用的数据映射器模式推荐的设计模式。这意味着我们使用管理器(或者服务,如果您愿意的话)来处理与数据库的所有交互。SqlAlchemy unchained包含两个类,以便尽可能地简化此过程:sessionmanager和modelmanager
sessionmanager是一个具体的类,您可以在需要与数据库会话交互时直接使用它。modelmanager是会话管理器的抽象子类应用程序中的模型:
$ pip install sqlalchemy-unchained5
两个模型管理器都是单例的,所以无论何时调用sess都是单例的。ionmanager()或yourmodelmanager()
,您将始终获得相同的实例。
包含元选项
表格(\u tablename\uuu
)
$ pip install sqlalchemy-unchained6
设置为自定义模型数据库中表的名称。默认情况下,我们使用模型的类名转换为snake case。
注意:所使用的snake case逻辑与flask sqlalchemy略有不同,因此如果要移植模型,并且其中任何一个模型都有连续的大写字母,则可能需要更改默认值。
pk(主键列)
$ pip install sqlalchemy-unchained7
设置为字符串可自定义用于主键的列名,设置为none
可禁用该列。
注意:自定义用于所有模型的默认主键列名与自定义其他元选项的默认列名不同。(您应该将\u modelregistry
子类化,并设置其默认的\u主键列
属性。这对于外键
帮助函数正常工作是必需的。)
创建时间(行插入时间戳)
$ pip install sqlalchemy-unchained8
设置为字符串可自定义用于创建时间戳的列名,或设置为none
可禁用该列。
更新时间(上次更新的时间戳)
$ pip install sqlalchemy-unchained9
设置为字符串可自定义用于更新时间戳的列名,或设置为none
可禁用该列。
repr(自动播放)
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py0
设置为列(属性)名称的元组以自定义模型的表示。
验证
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py1
设置为false
以禁用模型实例的验证。
多态(映射模型类层次结构)
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py2
默认情况下,此元选项处于禁用状态,可以设置为 当启用多态性时,还有另外两个元选项可用于进一步自定义其行为:'joined'
、'single'
或true
('joined'的别名)。有关详细信息,请参见有关类继承层次结构的sqlalchemy文档。
存储在列中,该列默认为'discriminator'mkdir your-project &&cd your-project &&\
mkdir your_package && mkdir db &&\
touch setup.py your_package/config.py your_package/db.py your_package/models.py
3
多态标识
是sqlalchemy用来区分行应该使用哪个模型类的标识符,默认情况下使用模型的类名。多态标识
重要:应仅在层次结构的基础模型上指定多态性
和多态性
元选项。相反,如果要自定义多态标识,则应在层次结构中的每个模型上指定它。
模型验证
sqlalchemy unchained在将模型持久化到数据库之前添加了对验证模型的支持。这是默认启用的,although您可以使用验证元选项禁用它。启用验证后,默认情况下,所有不可为空的标量值列都将使用必需的" rel="nofollow">验证。
有两种不同的方法可以为您的模型编写自定义验证。
第一种方法是扩展basevalidatorbasevalidator,实现\uu call
,并提升验证错误如果验证失败:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py4
第二种方法是直接在模型类上定义验证classmethod
或staticmethod
。
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py5
在模型类上定义的验证方法必须遵循特定的命名约定:要么validate\lt;column\u name>;
要么validates\lt;column\u name>;
将起作用。正如在basevalidator上实现\u call\code>时,模型验证方法应该引发验证错误如果验证失败。
无论何时创建或更新模型实例,都会自动进行验证。如果任何验证程序失败,将引发验证程序错误。
自定义元选项
可用的元选项是可配置的。让我们来看看在元选项中创建的的实现:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py6
例如,假设您希望每个模型都有一个必需的名称列,但是没有自动的时间戳行为。首先,我们需要实现acolumnMetaOption:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py7
最后一步是告诉sqlalchemy unchained使用我们定制的basemodel
类:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py8
自定义默认主键列名
主键列是特殊的,因为在创建模型类期间,确定外键列名需要了解其设置。第一步是子类化\u modelregistry
并设置其default\u primary\u列
类属性:
mkdir your-project &&cd your-project &&\ mkdir your_package && mkdir db &&\ touch setup.py your_package/config.py your_package/db.py your_package/models.py9
然后,为了通知sqlalchemy关于您的自定义模型注册表的信息,您需要调用model registry。
# your_package/config.pyimportosclassConfig:PROJECT_ROOT=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))DATABASE_URI='sqlite:///'+os.path.join(PROJECT_ROOT,'db','dev.sqlite')0
惰性映射(实验)
惰性映射是这个包在sqlalchemy之上引入的特性。它是实验性的,默认情况下是禁用的。在常用的sqlalchemy中,定义模型时,在代码被导入的第二天,基本模型的元类将向sqlalchemy的映射器注册模型。99%的情况下,这是您希望发生的,但是如果由于某种原因您不希望发生这种行为,那么您必须启用惰性映射。启用惰性映射有两个组件。
第一步是自定义模型注册表:
# your_package/config.pyimportosclassConfig:PROJECT_ROOT=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))DATABASE_URI='sqlite:///'+os.path.join(PROJECT_ROOT,'db','dev.sqlite')1
就像自定义主键列一样,我们需要通过调用modelregistry来通知我们的子类的modelregistry。
# your_package/config.pyimportosclassConfig:PROJECT_ROOT=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))DATABASE_URI='sqlite:///'+os.path.join(PROJECT_ROOT,'db','dev.sqlite')2
最后一步是像这样定义您的模型:
# your_package/config.pyimportosclassConfig:PROJECT_ROOT=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))DATABASE_URI='sqlite:///'+os.path.join(PROJECT_ROOT,'db','dev.sqlite')3