Динамическое создание таблиц и сопоставление ORM в SqlAlchemy - PullRequest
13 голосов
/ 10 июня 2009

Я довольно новичок в использовании реляционных баз данных, поэтому я предпочитаю использовать хороший ORM для упрощения вещей. Я потратил время на оценку различных ORM Python и думаю, что SQLAlchemy - это то, что мне нужно. Однако я зашел в тупик.

Мне нужно создать новую таблицу, которая будет соответствовать каждому экземпляру игрока, который я создаю в таблице игроков моего приложения. Я думаю, что знаю, как создать таблицу, изменив имя таблицы с помощью метаданных, а затем вызвав функцию create, но я понятия не имею, как отобразить ее в новый динамический класс.

Может кто-нибудь дать мне несколько советов, которые помогут мне преодолеть замораживание моего мозга? Это вообще возможно?

Примечание: я открыт для других ORM в Python, если то, что я прошу, легче реализовать. Просто покажите мне, как: -)

Ответы [ 6 ]

23 голосов
/ 10 июня 2009

Мы абсолютно избалованы SqlAlchemy.
То, что следует ниже, взято непосредственно из учебника ,
и действительно легко установить и начать работать.

И поскольку это делается так часто,
Майк Байер сделал это еще проще
с «все в одном» «декларативным» методом .

Настройка вашей среды (я использую базу данных 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

Если у вас включено ведение журнала, вы увидите SQL, который SqlAlchemy создает для вас.

Определите свой класс:

>>> 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

Вот и все, теперь у вас есть игровой стол.
Кроме того, SqlAlchemy googlegroup великолепна.
Майк Байер очень быстро отвечает на вопросы.

3 голосов
/ 10 июня 2009

Может быть, посмотрите на SQLSoup , который является слоем над SQLAlchemy.

Вы также можете создавать таблицы, используя обычный SQL, и для динамического отображения используйте эти библиотеки, если у них уже нет функции создания таблиц.

Или, альтернативно, создайте динамический класс и отобразите его:

tableClass = type(str(table.fullname), (BaseTable.BaseTable,), {})
mapper(tableClass, table)

где BaseTable может быть любым классом Python, от которого вы хотите наследовать все классы вашей таблицы, например такой класс Base может иметь некоторые полезные или общие методы, например, основные методы CRUD:

class BaseTable(object): pass

В противном случае вам не нужно передавать какие-либо базы на type(...).

2 голосов
/ 27 июня 2009

вы можете использовать декларативный метод для динамического создания таблиц в базе данных

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
1 голос
/ 23 февраля 2019

Это очень старый вопрос. В любом случае, если вы предпочитаете 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()

Создавая фабрику классов, можно легко присваивать имена классу и таблице базы данных.

1 голос
/ 24 октября 2009

Я столкнулся с той же проблемой, когда пытался автоматизировать простые задачи CRUD с помощью SQLAlchemy. Вот простое объяснение и некоторый код: http://www.devx.com/dbzone/Article/42015

0 голосов
/ 09 мая 2013

возможно я не совсем понял, что вы хотите, но этот рецепт создает идентичные столбцы в разных __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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...