Добавить поддержку базы данных во время выполнения - PullRequest
1 голос
/ 17 марта 2012

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

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Product(object):
    pass

class WebSession(Product):
    pass

class Malware(WebSession):
    pass

class DBProduct(Product, Base):
    pass

class DBWebSession(WebSession, DBProduct):
    pass

class DBMalware(Malware, DBWebSession):
    pass

Однако,Я чувствую, что должен быть более простой / чистый способ сделать это.Я чувствую, что создаю беспорядок наследования и потенциальные проблемы в будущем.В идеале я хотел бы создать один класс Product, WebSession и т. Д. (Возможно, с использованием декораторов), который содержит информацию, необходимую для использования БД, но он включается / работает только после вызова чего-то вроде enable_db_support().После вызова этой функции, независимо от того, какой объект я создаю, он сам (и все объекты, которые он наследует) включает все привязки столбцов и т. Д. Я должен также отметить, что если я каким-то образом выясню, как включить Product и DBProduct в одном классе мне иногда нужны 2 версии одной и той же функции: 1, которая вызывается, если включена поддержка db, и 1, если она не включена.Я также подумал о «воссоздании» иерархии объектов при вызове enable_db_support(), однако это также оказалось кошмаром.

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 17 марта 2012

Что ж, вы, вероятно, можете обойтись без создания модели без учета БД, используя Classical Mapping без использования расширения declarative. В этом случае, однако, вы не сможете использовать relationships, как они используются в SA, но для простых типов импорта / экспорта данных этого должно быть достаточно:

# models.py
class User(object):
    pass

----

# mappings.py
from sqlalchemy import Table, MetaData, Column, ForeignKey, Integer, String
from sqlalchemy.orm import mapper
from models import User

metadata = MetaData()

user = Table('user', metadata,
            Column('id', Integer, primary_key=True),
            Column('name', String(50)),
            Column('fullname', String(50)),
            Column('password', String(12))
        )

mapper(User, user)

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

0 голосов
/ 17 марта 2012

Мне кажется, что СУЩЕСТВЕННО, что нужно сделать, это абстрагироваться от деталей вашего формата хранения данных, будь то обычный текстовый файл или база данных.

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

Или, другими словами, ненаписать Product и DB_Product класс.Вместо этого напишите функцию store_data(), которой можно сказать использовать format='text' или format='db'.Затем используйте это везде.

Это фактически то же самое, что SQLAlchemy делает за кулисами - вам не нужно писать отдельный код для SQLAlchemy в зависимости от того, управляет ли он MySQL, PostgreSQL и т. Д.SQLAlchemy, и вы используете абстрагированный (нейтральный к базе данных) интерфейс.


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


Поочередно поочередно используйте sqlite3 в качестве промежуточного формата.Поэтому перепишите все ваш код, чтобы использовать sqlite3, а затем переведите из sqlite3 в обычный текст (или другую базу данных), как требуется.В предельном случае преобразование в простой текст только на расстоянии sqlite3 db .dump.

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