[英]Dynamic Table Creation and ORM mapping in SqlAlchemy
我对使用关系数据库还很陌生,所以我更喜欢使用好的 ORM 来简化事情。 我花时间评估了不同的 Python ORM,我认为 SQLAlchemy 正是我所需要的。 然而,我已经到了精神上的死胡同。
我需要创建一个新表,以配合我在应用程序的播放器表中创建的每个播放器实例。 我想我知道如何通过元数据更改表的名称然后调用 create 函数来创建表,但我不知道如何将其映射到新的动态类。
有人可以给我一些提示来帮助我摆脱大脑冻结吗? 这甚至可能吗?
注意:如果我要问的更容易实现,我对 Python 中的其他 ORM 持开放态度。只要告诉我如何:-)
我们被 SQLAlchemy 宠坏了。
以下内容直接取自教程,
并且非常容易设置和开始工作。
而且因为经常这样做,
该文档于 2011 年 8 月变为完全声明性的。
设置您的环境(我正在使用 SQLite 内存数据库进行测试):
>>> from sqlalchemy import create_engine
>>> engine = create_engine('sqlite:///:memory:', echo=True)
>>> from sqlalchemy import Table, Column, Integer, String, MetaData
>>> metadata = MetaData()
定义你的表:
>>> players_table = Table('players', metadata,
... Column('id', Integer, primary_key=True),
... Column('name', String),
... Column('score', Integer)
... )
>>> metadata.create_all(engine) # create the table
如果您打开了日志记录,您将看到 SQLAlchemy 为您创建的 SQL。
定义你的类:
>>> class Player(object):
... def __init__(self, name, score):
... self.name = name
... self.score = score
...
... def __repr__(self):
... return "<Player('%s','%s')>" % (self.name, self.score)
将类映射到您的表:
>>> from sqlalchemy.orm import mapper
>>> mapper(Player, players_table)
<Mapper at 0x...; Player>
创建一个播放器:
>>> a_player = Player('monty', 0)
>>> a_player.name
'monty'
>>> a_player.score
0
就是这样,你现在有一个你的玩家表。
这是一个非常古老的问题。 无论如何,如果您更喜欢 ORM,那么生成具有类型的表类非常容易:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
Test = type('Test', (Base,), {
'__tablename__': 'test',
'test_id': Column(Integer, primary_key=True, autoincrement=True),
'fldA': Column(String),
... other columns
}
)
Base.metadata.create_all(engine)
# passed session create with sqlalchemy
session.query(Test).all()
制作类工厂,很容易为类和数据库表分配名称。
如果您正在寻找创建动态类和表,您可以使用以下基于我在此处找到的教程 URL 的技术( http://sparrigan.github.io/sql/sqla/2016/01/03/dynamic-tables.html ),我稍微修改了他的做法。
from sqlalchemy import create_engine
engine = create_engine('sqlite:///test.db', echo=True)
from sqlalchemy import Column, Integer,Float,DateTime, String, MetaData
metadata = MetaData()
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session() # create a Session
Base = declarative_base()
首先包含所有需要的依赖项并创建您的会话和 Base。
动态创建它的关键在这里:
attr_dict = {'__tablename__': 'default','id': Column(Integer, primary_key=True, auto_increment=True)}
您可以通过利用 python 中的“类型”函数来创建一个表。
myClass = type('ClassnameHere', (Base,), attr_dict)
请注意,我们传入的是attr_dict ,这将为我们的类提供所需的表名和列信息,但不同之处在于我们通过字符串定义类名! 这意味着您可以创建一个循环,例如遍历字符串数组以开始动态创建表!
接下来你要做的就是简单地调用
Base.metadata.create_all(engine)
因为我们创建的动态类继承自Base该命令将简单地创建表!
您现在添加到此表中,例如:
SomeRow = myClass(id='2')
session.add(SomeRow)
session.commit()
如果您也不知道列名,这可以更进一步。 只需参考文章即可了解如何执行此操作。
你基本上会做这样的事情:
firstColName = "Ill_decide_later"
secondColName = "Seriously_quit_bugging_me"
new_row_vals = myClass(**{firstColName: 14, secondColName: 33})
** 运算符获取对象并将其解包,以便 firstColName 和 secondColName 添加赋值运算符,因此它本质上与此相同:
new_row_vals = myClass(firstColName=14, secondColName=33)
这种技术的优点是现在您可以动态添加到表中,甚至不必定义列名!
例如,这些列名可以存储在字符串数组中,或者您想要的任何内容中,您只需从那里获取它。
也许看看SQLSoup ,它是 SQLAlchemy 上的一层。
您还可以使用普通 SQL 创建表,并动态映射,如果这些库没有创建表功能,请使用这些库。
或者创建一个动态类并映射它:
tableClass = type(str(table.fullname), (BaseTable.BaseTable,), {})
mapper(tableClass, table)
其中 BaseTable 可以是您希望所有表类都继承自的任何 Python 类,例如此类Base
类可能具有一些实用程序或通用方法,例如基本的 CRUD 方法:
class BaseTable(object): pass
否则,您无需将任何基数传递给type(...)
。
您可以使用声明性方法在数据库中动态创建表
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
Base = declarative_base()
class Language(Base):
__tablename__ = 'languages'
id = Column(Integer, primary_key=True)
name = Column(String(20))
extension = Column(String(20))
def __init__(self, name, extension):
self.name = name
self.extension = extension
当我尝试使用 SQLAlchemy 自动执行简单的 CRUD 任务时,我遇到了同样的问题。 这是简单的解释和一些代码: http : //www.devx.com/dbzone/Article/42015
也许我不太明白你想要什么,但是这个食谱在不同的 __tablename__ 中创建了相同的列
class TBase(object):
"""Base class is a 'mixin'.
Guidelines for declarative mixins is at:
http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#mixin-classes
"""
id = Column(Integer, primary_key=True)
data = Column(String(50))
def __repr__(self):
return "%s(data=%r)" % (
self.__class__.__name__, self.data
)
class T1Foo(TBase, Base):
__tablename__ = 't1'
class T2Foo(TBase, Base):
__tablename__ = 't2'
engine = create_engine('sqlite:///foo.db', echo=True)
Base.metadata.create_all(engine)
sess = sessionmaker(engine)()
sess.add_all([T1Foo(data='t1'), T1Foo(data='t2'), T2Foo(data='t3'),
T1Foo(data='t4')])
print sess.query(T1Foo).all()
print sess.query(T2Foo).all()
sess.commit()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.