使用 SQLAlchemy 基于类自动构建数据库表

Posted

技术标签:

【中文标题】使用 SQLAlchemy 基于类自动构建数据库表【英文标题】:Automatically Build Database Table based on a Class with SQLAlchemy 【发布时间】:2013-05-15 21:18:57 【问题描述】:

我真的是 SQLAlchemy 的新手,我喜欢它。现在我手动做很多事情,我想做更多“python”和动态的事情。

举个例子,我有一个简短的脚本,可以手动创建/定义一个表,然后是一个将数据插入该表的函数。

数据库连接

import os
from sqlalchemy import *
from sqlalchemy import schema, types
from sqlalchemy.ext.declarative import declarative_base  

db_url = os.environ.get('DATABASE_URL')
engine = create_engine(db_url)
Base = declarative_base(engine)
meta = Base.metadata

表定义

file_paths = Table('file_paths', meta,
    Column('table_id', Integer, primary_key = True),
    Column('fullpath', String(255)),
    Column('filename', String(255)),
    Column('extension', String(255)),
    Column('created', String(255)),
    Column('modified', String(255)),
    Column('size', Integer),
    Column('owner', String(255)),
    Column('permissions', Integer),
    mysql_engine='InnoDB',
)
file_paths.drop(engine, checkfirst = False)
file_paths.create(engine, checkfirst = True)

插入函数接受一个字符串和一个列表作为参数

def push_to_db(fullpath, fileInfo):
    i = file_paths.insert()
    i.execute(  fullpath    = str(fullpath), 
            filename    = str(fileInfo[0]),
            extension   = str(fileInfo[1]),
            created     = str(fileInfo[2]),
            modified    = str(fileInfo[3]),
            size        = str(fileInfo[4]),
            owner       = str(fileInfo[5]),
            permissions = str(fileInfo[6]),
         )

这可行,但它很丑陋,并且是从我在网上某处找到的教程中摘录的。我的目标是让这些操作动态化。

示例类

class FileMeta(object):
    def __init__(self, fullPathFileName, filename):
        self.fullPathFileName = fullPathFileName
        self.filename = filename
        self.extension = os.path.splitext(self.filename)[1].lower()
        ...

    def fileMetaList(self):
        return [self.filename, self.extension, self.created, self.modified,\
                self.size, self.owner, self.permissions]

所以这是场景:给定一个类对象

    根据类成员变量动态定义表 列号和名称应与变量名对应 或对应于类变量列表中该变量的索引 编写一个函数,可以将类中的数据插入到对应的动态创建的表中

我的直觉告诉我这就是 SQLAlchemy 的优势所在。谁能告诉我一个很好的教程或参考,可以概述这个过程?

【问题讨论】:

你的意思是declarative object-relational configuration? 我不确定我的意思。我是 SQLAlchemy 的菜鸟。 【参考方案1】:

您想改用declarative extension:

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class FilePaths(Base):
    __tablename__ = 'file_paths'
    __table_args__ = 'mysql_engine':'InnoDB'

    table_id = Column(Integer, primary_key=True)
    fullpath = Column(String(255))
    filename = Column(String(255))
    extension = Column(String(255))
    created = Column(String(255))
    modified = Column(String(255))
    size = Column(Integer)
    owner = Column(String(255))
    permissions = Column(Integer)

Base.metadata.create_all(engine)

您可以根据需要定义自己的__init__() 以及其他方法,然后创建这些方法的实例以插入新行。

请参阅SQLAlchemy's own ORM tutorial。

【讨论】:

@laycat:这是 OP 要求的:将表行反映为对象的类定义。您现在可以使用 FilePath 实例,它们透明地反映数据库行内容。 Base 的 AutoMap() 是否也适用于动态创建表格? docs.sqlalchemy.org/en/rel_1_0/orm/extensions/automap.html @DustyBoshoff 看起来像是为此目的而设计的,是的。请注意,该扩展是在 0.9.1 中添加的;这个答案是0.8天写的。 @DustyBoshoff:实际上,automapper 从现有模式(尽管是初级模式)创建声明性类; OP 试图手动创建类(这为您提供了更多的灵活性和控制力),但使用了错误的工具。【参考方案2】:

添加自动地图扩展:

from sqlalchemy.ext.automap import automap_base

# SQLAlchemy
engine = create_engine(DATABASE_URL)
metadata = MetaData()

Base = automap_base()
Base.prepare(engine, reflect=True)

【讨论】:

以上是关于使用 SQLAlchemy 基于类自动构建数据库表的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy Automap不为没有主键的表创建类

SQLAlchemy

SQLAlchemy框架用法详解

SqlAlchemy 将新字段添加到类并在表中创建相应的列

利用sqlalchemy 查询视图

Flask-SQLAlchemy