Подтвердить что ты не робот

SQLAlchemy и несколько баз данных

У меня есть набор похожих (но не идентичных) баз данных и хотел бы использовать SQLAlchemy как способ "стандартизации" доступа. Базы данных могут отличаться очень незначительно, например, иметь уникальный префикс в именах столбцов или они могут отличаться более резко, а также отсутствовать столбцы (или для старых баз данных, отсутствующие целые таблицы).

Я ищу помощь, это не столько проблема SQLAlchemy, сколько Python/Organizational. Как я могу настроить несколько баз данных, которые могут быть повторно использованы в проектах?

Я читал о сеансах SQLAlchemy, но не вижу способа использовать их без создания каждого из них каждого проекта.

Мой вопрос в следующем: как я могу сделать модуль/пакет, который будет содержать множество настроек модели базы данных, которые будут использоваться в SQLAlchemy, которые могут быть легко импортированы/использованы в другом проекте python?

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

Любые ресурсы, указатели или материалы для чтения по этой теме будут по достоинству оценены. Спасибо заранее, и я сожалею, если в этом ответе было что-то еще, поиски не показали ничего, что связано с этим.

EDIT. Я оставил оригинал неповрежденным и добавляю больше контента на основе совета Paul.

RE: SA ORM - Да, я планирую использовать ORM SQLAlchemy. По каким-то очевидным причинам я не могу предоставить реальные базы данных. Однако предположим, что эти три фиктивные базы данных, точно названные DB1, DB2 и DB3 (мы возьмем по одной таблице в каждой, всего несколько столбцов, в реальном мире будет значительно больше того и другого).

Каждая база данных имеет таблицу пользователя с несколькими столбцами в каждой. Ниже приведены некоторые обозначения SQL для таблиц/столбцов:

DB1.user  --> DB1.user.id,      DB1.user.username,  DB1.user.email
DB2.user  --> DB2.user.id,      DB2.user.user_name, DB2.user.email
DB3._user --> DB3._user.userid, DB3._user.username, DB3.user.email_address

В настоящее время я пытаюсь разделить эти базы данных на "модульные" и иметь возможность просто добавлять дополнительные базы данных, когда я иду.

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

Databases         |    Databases            |    Databases
    DB1.py        |        DB1              |        DB1
    DB2.py        |            models.py    |            models
    DB3.py        |        DB2              |                user.py
                  |            models.py    |                anothertable.py
                  |        DB2              |        ...
                  |            models.py    |        DB3
                  |                         |            models
                  |                         |                user.py
                  |                         |                anothertable.py

Мне бы хотелось иметь доступ к ним с помощью SA ORM и делать это с минимальным количеством импортирующих/деклараций, насколько это возможно, когда приходит время использовать эти базы данных в файле python. Нужно сделать что-то похожее:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from Database import DB1, ..., DB[N]
db1_engine = create_engine('connect_string/db1')
db1_session = sessionmaker(bind=db1_engine)()
...
db3_engine = create_engine('connect_string/db3')
db3_session = sessionmaker(bind=db3_engine)()

будет невероятно громоздким, поскольку я буду иметь дело с гораздо большим количеством, чем только три базы данных. Я бы предпочел, чтобы это уже позаботилось обо мне (в файле __init__.py, может быть?)

Возможность доступа к нему и его использования аналогично:

import Databases

Databases.DB1.session.query('blahblah')

будет бесконечно лучше.

EDIT2. Я также знаю, как обойти варианты в соглашениях об именах баз данных/столбцов при настройке моих моделей. Это не проблема, но я упомянул об этом так, что было известно, что я не могу просто использовать один набор моделей для нескольких баз данных.

Надеюсь, расширив это, я не мутировал воды и не делал это слишком запутанным. Спасибо, что нашли время, чтобы прочитать его!

EDIT3: мне удалось потратить немного больше времени на это. Я создал проект следующим образом:

Databases
    __init__.py
    databases.py
    settings.py
    DB1
        __init__.py
        models.py
    ...
    DB3
        __init__.py
        models.py

В настоящее время у меня есть набор баз данных, которые "установлены" в файле settings.py. Каждой записи будет нравится INSTALLED_DATABASES = ('DB1', ..., 'DB3'). Когда я заканчиваю больше моделей, и они добавляются в список туферов. Это позволяет мне добавлять или удалять контент по ходу.

У меня есть установка engine и sessios внутри файла models.py и файл init.py для каждой настройки базы данных from models import *.

В файле databases.py у меня есть следующие

class Databases(object):
    def __init__(self):
        for database in INSTALLED_DATABASES:
            setattr(self, database, __import__(database))

Теперь я могу использовать их через:

from databases import Databases

db = Databases()

for qr in db.DB1.query(db.DB1.User):
    print qr.userid, qr.username

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

У меня впереди еще много работы. Я хотел бы создать объекты, которые заставляют валидацию модели (т.е. Присутствует ли данное поле? Имеет ли не существующее поле значение по умолчанию? И т.д.) И лучше включить, как это работает с моей IDE (в настоящее время это не так). Но я на правильном пути. Я решил, что обновляю это для всех, кто случайно может подумать, как сделать то же самое, что и я.

Извините, это стало так долго!

Ура!

4b9b3361

Ответ 1

В соответствии с запросами на мой первоначальный вопрос, я сделал третье редактирование и сделал это своим ответом. Поскольку я не уверен в правильных протоколах, я оставил третье редактирование на месте выше. Если вы уже прочитали EDIT3, вы прочитали, что у меня есть в качестве ответа.

Мне удалось потратить немного больше времени на это. Я создал проект следующим образом:

Databases
    __init__.py
    databases.py
    settings.py
    DB1
        __init__.py
        models.py
    ...
    DB3
        __init__.py
        models.py

В настоящее время у меня есть набор баз данных, которые "установлены" в файле settings.py. Каждой записи понравится INSTALLED_DATABASES = ('DB1', ..., 'DB3'). Когда я заканчиваю больше моделей, и они добавляются в список туферов. Это позволяет мне добавлять или удалять контент по ходу.

У меня есть установка engine и sessios внутри файла models.py и файл init.py для каждой настройки базы данных from models import *.

В файле databases.py у меня есть следующие

class Databases(object):
    def __init__(self):
        for database in INSTALLED_DATABASES:
            setattr(self, database, __import__(database))

Теперь я могу использовать их через:

from databases import Databases

db = Databases()

for qr in db.DB1.query(db.DB1.User):
    print qr.userid, qr.username

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

У меня впереди еще много работы. Я хотел бы создать объекты, которые заставляют валидацию модели (т.е. Присутствует ли данное поле? Имеет ли не существующее поле значение по умолчанию? И т.д.) И лучше включить, как это работает с моей IDE (в настоящее время это не так). Но я на правильном пути. Я решил, что обновляю это для всех, кто случайно может подумать, как сделать то же самое, что и я.

Извините, это стало так долго!

Ура!

Ответ 2

Ваше решение выглядит неплохо. Вот что я сделал.

У меня есть пакет с именем connector, а в нем модуль для каждого db, а также файл настроек.

Каждый из этих соединительных модулей создает свою строку соединения и свой движок вместе с декларативной базой и классами для таблиц.

Затем появляется метод loadSession, который возвращает сеанс (этот я получил из учебника или другого сообщения здесь, не могу точно вспомнить), и еще один, который я добавил, который возвращает движок, если я хочу что-то сделать с этим.

Итак, тогда в каком-то другом модуле программы я бы сделал что-то вроде этого

from connectors import x, y, z

x_ses = x.loadSession()
y_ses = y.loadSession()
z_ses = z.loadSession()

xq = x_ses.query(...)
yq = y_ses.query(...)