当sqlalchemy ORM class 属性与数据库列不同时,如何获取ORM class 属性列表?
When the sqlalchemy ORM class attributes are different from database columns, how to get a list of the ORM class attributes?
假设您想在 sqlalchemy 中迭代 ORM class 的 ORM 属性。
因此,您需要一个 ORM 属性列表。您如何获得该列表?
如果 ORM class 没有重命名属性,因此 ORM 属性与数据库列匹配,那么您可以使用以下解决方案:
(顺便说一下,源代码文件 /lib/sqlalchemy/orm/base.py 中还有一个内置(私有)函数 _orm_columns() 似乎提供了此功能)
但是如果 python ORM class 与数据库列的名称不同(例如在这 3 个 ORM 属性中):
>>> class User(Base):
... __tablename__ = 'users'
...
... id = Column('pkey', Integer, primary_key=True)
... name = Column('user_name', String)
... fullname = Column('human_name', String)
那这个方法就不行了。
那么,如何获得 ORM 属性的 python 版本呢?
我定义了一个 mixin class 来扩充
Base = declarative_base()
使用 mixin class 定义为:
import inspect
import sqlalchemy as sqla
class orm_mixin_class(object):
"""Additional functionality wanted in orm classes (that inherit from Base)."""
@classmethod
def orm_class_info(cls):
"""
Get info about the orm class (as opposed to the database table it is mapped to).
Returns:
list of dict where each dict describes a orm class attribute.
Keys: s_class_attribute_name
"""
o_leaf_level_class = cls # this turns out the be the leaf class instead of this mixin class
l_orm_attribute_pairs = inspect.getmembers(o_leaf_level_class)
l_orm_class_info_dicts = []
for (s_class_attribute_name, o_attr_type) in l_orm_attribute_pairs:
d_attr_info = {}
b_orm_attribute = False
try:
o_inspect = sqla.inspection.inspect(o_attr_type)
if isinstance(o_inspect, sqla.orm.attributes.QueryableAttribute):
b_orm_attribute = True
d_attr_info['s_class_attribute_name'] = s_class_attribute_name
except:
pass
if b_orm_attribute:
# only orm attributes have an entry in the output list
l_orm_class_info_dicts.append(d_attr_info)
return(l_orm_class_info_dicts)
因此可以从方法调用中轻松获取 ORM 属性列表。
ORM class 声明现在是:
class User(Base, orm_mixin_class):
这已经使用 inspection system:
实现
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import inspect
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
x = Column(Integer)
y = Column(Integer)
print inspect(A).c
print inspect(A).c.x
print inspect(A).column_attrs
print inspect(A).column_attrs.x
print inspect(A).column_attrs.x.expression
http://docs.sqlalchemy.org/en/latest/core/inspection.html
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.columns
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.column_attrs
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.c
假设您想在 sqlalchemy 中迭代 ORM class 的 ORM 属性。 因此,您需要一个 ORM 属性列表。您如何获得该列表?
如果 ORM class 没有重命名属性,因此 ORM 属性与数据库列匹配,那么您可以使用以下解决方案: (顺便说一下,源代码文件 /lib/sqlalchemy/orm/base.py 中还有一个内置(私有)函数 _orm_columns() 似乎提供了此功能)
但是如果 python ORM class 与数据库列的名称不同(例如在这 3 个 ORM 属性中):
>>> class User(Base):
... __tablename__ = 'users'
...
... id = Column('pkey', Integer, primary_key=True)
... name = Column('user_name', String)
... fullname = Column('human_name', String)
那这个方法就不行了。 那么,如何获得 ORM 属性的 python 版本呢?
我定义了一个 mixin class 来扩充
Base = declarative_base()
使用 mixin class 定义为:
import inspect
import sqlalchemy as sqla
class orm_mixin_class(object):
"""Additional functionality wanted in orm classes (that inherit from Base)."""
@classmethod
def orm_class_info(cls):
"""
Get info about the orm class (as opposed to the database table it is mapped to).
Returns:
list of dict where each dict describes a orm class attribute.
Keys: s_class_attribute_name
"""
o_leaf_level_class = cls # this turns out the be the leaf class instead of this mixin class
l_orm_attribute_pairs = inspect.getmembers(o_leaf_level_class)
l_orm_class_info_dicts = []
for (s_class_attribute_name, o_attr_type) in l_orm_attribute_pairs:
d_attr_info = {}
b_orm_attribute = False
try:
o_inspect = sqla.inspection.inspect(o_attr_type)
if isinstance(o_inspect, sqla.orm.attributes.QueryableAttribute):
b_orm_attribute = True
d_attr_info['s_class_attribute_name'] = s_class_attribute_name
except:
pass
if b_orm_attribute:
# only orm attributes have an entry in the output list
l_orm_class_info_dicts.append(d_attr_info)
return(l_orm_class_info_dicts)
因此可以从方法调用中轻松获取 ORM 属性列表。
ORM class 声明现在是:
class User(Base, orm_mixin_class):
这已经使用 inspection system:
实现from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import inspect
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
x = Column(Integer)
y = Column(Integer)
print inspect(A).c
print inspect(A).c.x
print inspect(A).column_attrs
print inspect(A).column_attrs.x
print inspect(A).column_attrs.x.expression
http://docs.sqlalchemy.org/en/latest/core/inspection.html
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.columns
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.column_attrs
http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.c