转载请标明地址https://blog.csdn.net/weixin_42068117/article/details/83857355
https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/sql/schema.py
"""Symbol indicating that a :class:`.Table` or :class:`.Sequence`
should have 'None' for its schema, even if the parent
:class:`.MetaData` has specified a schema.
.. versionadded:: 1.0.14
"""
def _get_table_key(name, schema):
if schema is None:
return name
else:
return schema + "." + name
这一段代码显示的是我们给定的schema会拼接数据库的名字。大家应该可以理解是 数据库.表名 这样就不会有数据库的限制。这一段属于示例给大家理解的,如果只想知道怎么用,直接看本文最后的代码示例就可以了。
class Table(DialectKWArgs, SchemaItem, TableClause):
"""
The :class:`.Table` object constructs a unique instance of itself based
on its name and optional schema name within the given
:class:`.MetaData` object. Calling the :class:`.Table`
constructor with the same name and same :class:`.MetaData` argument
a second time will return the *same* :class:`.Table` object - in this way
the :class:`.Table` constructor acts as a registry function.
:param schema: The schema name for this table, which is required if
the table resides in a schema other than the default selected schema
for the engine's database connection. Defaults to ``None``.
If the owning :class:`.MetaData` of this :class:`.Table` specifies
its own :paramref:`.MetaData.schema` parameter, then that schema
name will be applied to this :class:`.Table` if the schema parameter
here is set to ``None``. To set a blank schema name on a :class:`.Table`
that would otherwise use the schema set on the owning :class:`.MetaData`,
specify the special symbol :attr:`.BLANK_SCHEMA`.
.. versionadded:: 1.0.14 Added the :attr:`.BLANK_SCHEMA` symbol to
allow a :class:`.Table` to have a blank schema name even when the
parent :class:`.MetaData` specifies :paramref:`.MetaData.schema`.
The quoting rules for the schema name are the same as those for the
``name`` parameter, in that quoting is applied for reserved words or
case-sensitive names; to enable unconditional quoting for the
schema name, specify the flag
``quote_schema=True`` to the constructor, or use the
:class:`.quoted_name` construct to specify the name.
"""
:param name: The name of this table as represented in the database.
参数代表数据库的名字。
def __init__(self, *args, **kw):
"""Constructor for :class:`~.schema.Table`.
This method is a no-op. See the top-level
documentation for :class:`~.schema.Table`
for constructor arguments.
"""
# __init__ is overridden to prevent __new__ from
# calling the superclass constructor.
在这个类的 __init__ 方法中,又对此方式介绍了一下。
以下是实例一,是调用的第一种方法,直接作为库名配置,这种是配置到框架内需要的。如果__table_args__有做其他配置
from flask import Flask
import datetime
from sqlalchemy import Column, String, create_engine, DateTime, func
app = Flask(__name__)
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import sessionmaker, scoped_session
# Base = declarative_base(cls=DeferredReflection)
Base = declarative_base()
class testuser(Base):
__tablename__ = 'testuser'
# 当前数据库名字是 test
__table_args__ = {'schema': 'test'}
id = Column(String(20), primary_key=True)
name = Column(String(20))
woncreated = Column(DateTime, default=datetime.datetime.utcnow())
wontimestamp = Column(DateTime, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
#
class testuser2(Base):
__tablename__ = 'testuser2'
# 关联查询的另一个数据库是 test2
__table_args__ = {'schema': 'test2'}
id = Column(String(20), primary_key=True)
name = Column(String(20))
woncreated = Column(DateTime, default=datetime.datetime.utcnow())
wontimestamp = Column(DateTime, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
engine = create_engine('mysql+pymysql://*****:*****@zch.zhangchenghao.cn/test')
# Base.prepare(engine)
dbsession = scoped_session(sessionmaker(
autocommit=False, autoflush=False, bind=engine))
@app.route('/')
def index():
import pdb;
pdb.set_trace()
qq = dbsession.query(testuser).join(testuser2,
testuser.id == testuser2.id).all()
return str(tuple(q.__dict__ for q in qq))
if __name__ == '__main__':
app.run()
ORM 结果 如下,表名带前缀为数据库名
SELECT
test.testuser.id
AS
test_testuser_id, test.testuser.name
AS
test_testuser_name, test.testuser.woncreated
AS
test_testuser_woncreated, test.testuser.wontimestamp
AS
test_testuser_wontimestamp
FROM
test.testuser
INNER
JOIN
test2.testuser2
ON
test.testuser.id = test2.testuser2.id
结果
({'_sa_instance_state':, 'woncreated'
: None, 'wontimestamp': None, 'name': '1', 'id': '1'}, {'_sa_instance_state':, 'woncreated': None, 'wontimestamp': None, 'name': '2', 'id': '2'})
以下是实例二。需要做session,map,大体还是相同的,这个用法官方文档中也有,只是比较隐蔽。
import datetime
from sqlalchemy import Column, String, DateTime
from sqlalchemy import create_engine, Index, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import sessionmaker, scoped_session
# Base = declarative_base(cls=DeferredReflection)
Base = declarative_base()
class testuser(Base):
__tablename__ = 'testuser'
__table_args__ = (UniqueConstraint('id', 'name', name='user_settings_unique'),)
id = Column(String(20), primary_key=True)
name = Column(String(20))
woncreated = Column(DateTime, default=datetime.datetime.utcnow())
wontimestamp = Column(DateTime, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
'''__table_args__ = (
UniqueConstraint('UserId', 'DeviceUUID', 'EventId', 'NotificationCategory', name='uk_NotifyPush'),
{'schema': 'msus-service', 'extend_existing': True},
)'''
# 注意顺序,这是一种共同使用的方法,还有子类等方法
class testuser2(Base):
__tablename__ = 'testuser2'
__table_args__ = {'schema': 'test__2'}
id = Column(String(20), primary_key=True)
name = Column(String(20))
woncreated = Column(DateTime, default=datetime.datetime.utcnow())
wontimestamp = Column(DateTime, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
engine = create_engine('mysql+pymysql://root:******@zch.zhangchenghao.cn/test')
# Base.prepare(engine)
# dbsession = scoped_session(sessionmaker(
# autocommit=False, autoflush=False, bind=engine))
Session = sessionmaker(autocommit=False, autoflush=False, bind=engine)
session = Session()
session.connection(execution_options={
"schema_translate_map": {"test__1": "test", "test__2": "test2"}})
import pdb;pdb.set_trace()
# will query from the ``account_one.user`` table
a = session.query(testuser2).get(1)
print(a.__dict__)
# 以下是结果和调试过程
{'_sa_instance_state': , 'wontimestamp': None, 'woncreated': None, 'id': '1', 'name': '11'}
(Pdb) print(session.query(testuser))
SELECT testuser.id AS testuser_id, testuser.name AS testuser_name, testuser.woncreated AS testuser_woncreated, testuser.wontimestamp AS testuser_wontimestamp
FROM testuser
(Pdb) print(session.query(testuser2))
SELECT test__2.testuser2.id AS test__2_testuser2_id, test__2.testuser2.name AS test__2_testuser2_name, test__2.testuser2.woncreated AS test__2_testuser2_woncreated, test__2.testuser2.wontimestamp AS test__2_testuser2_wontimestamp
FROM test__2.testuser2
(Pdb) session.get_bind()
Engine(mysql+pymysql://root:***@zch.zhangchenghao.cn/test)
这是连接相同地址的两个数据库,连接不同地址的数据库用到sqlalchemy的engine的binds, 不同的binds需要继承不同的抽象类或者有不同的设置名。