blu*_*onk 6 python postgresql sqlalchemy database-schema
我有一个现有的数据库,它有两个模式,命名为schools和students,包含在一个实例中,declarative_base并通过从该实例继承的两个不同类
class DirectorioEstablecimiento(Base):
    __table_args__ = {'schema': 'schools'}
    __tablename__ = 'addresses'
    # some Columns are defined here
和
class Matricula(Base):
    __table_args__ = {'schema': 'students'}
    __tablename__ = 'enrollments'
    # some Columns are defined here
我可以使用该Base实例Base.metadata.create_all(bind=engine)在我在 postgres 中拥有的测试数据库中重新创建它。如果我查询,我可以确认这是没有问题的pg_namespace
In [111]: engine.execute("SELECT * FROM pg_namespace").fetchall()
2017-12-13 18:04:01,006 INFO sqlalchemy.engine.base.Engine SELECT * FROM pg_namespace
2017-12-13 18:04:01,006 INFO sqlalchemy.engine.base.Engine {}
Out[111]: 
[('pg_toast', 10, None),
 ('pg_temp_1', 10, None),
 ('pg_toast_temp_1', 10, None),
 ('pg_catalog', 10, '{postgres=UC/postgres,=U/postgres}'),
 ('public', 10, '{postgres=UC/postgres,=UC/postgres}'),
 ('information_schema', 10, '{postgres=UC/postgres,=U/postgres}'),
 ('schools', 16386, None),
 ('students', 16386, None)]
并从 psql CLI
user# select * from pg_tables;
     schemaname     |          tablename           | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity 
--------------------+------------------------------+------------+------------+------------+----------+-------------+-------------
 schools            | addresses                    | diego      |            | t          | f        | f           | f
 students           | enrollments                  | diego      |            | t          | f        | f           | f
 pg_catalog         | pg_statistic                 | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_type                      | postgres   |            | t          | f        | f           | f
 pg_catalog         | pg_authid                    | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog         | pg_user_mapping              | postgres   |            | t          | f        | f           | f
-- other tables were omitted
但是,如果我想在其他一些实例中反映该数据库,则declarative_base什么也没有反映。
就像是
In [87]: Base.metadata.tables.keys()
Out[87]: dict_keys(['schools.addresses', 'students.enrollments'])
In [88]: new_base = declarative_base()
In [89]: new_base.metadata.reflect(bind=engine)
In [90]: new_base.metadata.tables.keys()
Out[90]: dict_keys([])
我知道reflect接受 aschema作为参数,但我想在反射期间立即获得所有这些参数。出于某种原因,我可以一次实现这一目标。
有没有办法做到这一点?
当您调用metadata.reflect()它时,它只会反映默认架构(search_path您拥有权限的第一个架构)。因此,如果您的 search_path 是,public,students,school它只会反映 schema 中的表public。如果您没有架构 public 的权限,public架构将被跳过并默认为仅反映students。
默认架构由 SELECT current_schema();
为了反映其他模式,您需要metadata.reflect()为每个模式调用。
metadata.reflect(schema='public')  # will reflect even if you do not have permissions on the tables in schema `public`, as long as you have access to pg_* system tables
metadata.reflect(schema='students')
metadata.reflect(schema='schools')
注意:当您使用显式架构进行反射时
反映的表 metadata.tables将具有表完全限定模式名称的键,如schema1.mytable,schema2.mytable任何冲突的表名都将被替换为后一个。如果您有任何同名的表,您应该实现您的函数 classname_for_table以使用模式名称作为名称的前缀。
使用架构为表名添加前缀的示例
def classname_for_table(base, tablename, table):
    schema_name = table.schema
    fqname = '{}.{}'.format(schema_name, tablename)
    return fqname
Base.prepare(classname_for_table=classname_for_table)
**作为奖励,这里有一个小片段,它将公开每个模式的动态子模块中的所有表,以便您可以访问它**
创建一个文件即。db.py并放置以下内容
from types import ModuleType
def register_classes(base, module_dict):
    for name, table in base.classes.items():
        schema_name, table_name = name.split('.')
        class_name = table_name.title().replace('_', '')
        if schema_name not in module_dict:
            module = module_dict[schema_name] = ModuleType(schema_name)
        else:
            module = module_dict[schema_name]
        setattr(module, class_name, table)
使用自动映射基础和__dict__要注册模式的模块的调用此函数。
 register_classes(base, globals())
或者
import db
db.register_classes(base, db.__dict__)
然后你会得到
import db
db.students.MyTable
db.schools.MyTable
| 归档时间: | 
 | 
| 查看次数: | 1693 次 | 
| 最近记录: |