簡體   English   中英

SqlAlchemy 中的動態表創建和 ORM 映射

[英]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()

示例 sqlalchemy 中的信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM