改进的声明性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-unchained
0

接下来,我们需要将alembic配置为使用已经配置好的相同数据库。这发生在db/migrations/env.py文件的顶部,该文件是为我们生成的alembic init db/migrations命令。修改以下行:

$ pip install sqlalchemy-unchained
1

为了使这些导入语句正常工作,我们需要安装我们的包。让我们创建一个最小的setup.py

$ pip install sqlalchemy-unchained
2

并将我们的软件包安装到您用于开发的虚拟环境中:

$ pip install sqlalchemy-unchained
3

这应该是迁移工作所需的全部。让我们为我们的模型生成一个迁移,并运行它:

$ pip install sqlalchemy-unchained
4

使用SessionManager和模型管理器

sqlalchemy uncheed鼓励采用sqlalchemy使用的数据映射器模式推荐的设计模式。这意味着我们使用管理器(或者服务,如果您愿意的话)来处理与数据库的所有交互。SqlAlchemy unchained包含两个类,以便尽可能地简化此过程:sessionmanagermodelmanager

sessionmanager是一个具体的类,您可以在需要与数据库会话交互时直接使用它。modelmanager是会话管理器的抽象子类应用程序中的模型:

$ pip install sqlalchemy-unchained
5

两个模型管理器都是单例的,所以无论何时调用sess都是单例的。ionmanager()yourmodelmanager(),您将始终获得相同的实例。

包含元选项

表格(\u tablename\uuu

$ pip install sqlalchemy-unchained
6

设置为自定义模型数据库中表的名称。默认情况下,我们使用模型的类名转换为snake case。

注意:所使用的snake case逻辑与flask sqlalchemy略有不同,因此如果要移植模型,并且其中任何一个模型都有连续的大写字母,则可能需要更改默认值。

pk(主键列)

$ pip install sqlalchemy-unchained
7

设置为字符串可自定义用于主键的列名,设置为none可禁用该列。

注意:自定义用于所有模型的默认主键列名与自定义其他元选项的默认列名不同。(您应该将\u modelregistry子类化,并设置其默认的\u主键列属性。这对于外键帮助函数正常工作是必需的。)

创建时间(行插入时间戳)

$ pip install sqlalchemy-unchained
8

设置为字符串可自定义用于创建时间戳的列名,或设置为none可禁用该列。

更新时间(上次更新的时间戳)

$ pip install sqlalchemy-unchained
9

设置为字符串可自定义用于更新时间戳的列名,或设置为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.py
0

设置为列(属性)名称的元组以自定义模型的表示。

验证

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
1

设置为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.py
2

默认情况下,此元选项处于禁用状态,可以设置为'joined''single'true'joined'的别名)。有关详细信息,请参见有关类继承层次结构的sqlalchemy文档。

当启用多态性时,还有另外两个元选项可用于进一步自定义其行为:

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用来区分行应该使用哪个模型类的标识符,默认情况下使用模型的类名。多态标识存储在列中,该列默认为'discriminator'

重要:应仅在层次结构的基础模型上指定多态性多态性元选项。相反,如果要自定义多态标识,则应在层次结构中的每个模型上指定它。

模型验证

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.py
4

第二种方法是直接在模型类上定义验证classmethodstaticmethod

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
5

在模型类上定义的验证方法必须遵循特定的命名约定:要么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.py
6

例如,假设您希望每个模型都有一个必需的名称列,但是没有自动的时间戳行为。首先,我们需要实现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.py
7

最后一步是告诉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.py
8

自定义默认主键列名

主键列是特殊的,因为在创建模型类期间,确定外键列名需要了解其设置。第一步是子类化\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.py
9

然后,为了通知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

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java为什么我的代码永远运行?它只是一堆带int的for循环,应该是递减的?   java如何更改IntelliJ IDEA中的XML缩进?   java如何使未填充的int数组不打印0?   eclipse My Weka Java代码结果*Weka*虚拟*STRING*用于*STRING*属性*   java泄漏了Windows com。安卓内部的政策恳求   java这个无限循环的原因是什么?   swing My标签在Java中很模糊   java如何在组件表示存储扩展中获取组件对象   java如何避免selenium网格中的会话超时   Java乘法测验,如果答案错误,如何循环   在Java HttpServlet Google app engine中保存对象   java ArrayList过滤器   java跳跃减慢了xvelocity:使用Libgdx/Box2D进行跳跃和跑步   java删除、复制和修改pom。xml文件   当提供的时区与服务器的时区相同时,RestCall中的java@DateTimeFormat(iso=iso.DATE_TIME)不工作   java Spring批处理多线程默认限制为10隐式?   安卓错误java。lang.UnsupportedOperationException:无法转换为维度:type=0x1