Использование Flask-SQLAlchemy без колбы

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

Моя модель выглядит так:

class IPEntry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ip_address = db.Column(db.String(16), unique=True)
    first_seen = db.Column(db.DateTime(),
        default = datetime.datetime.utcnow
    )
    last_seen = db.Column(db.DateTime(),
        default = datetime.datetime.utcnow
    )

    @validates('ip')
    def validate_ip(self, key, ip):
        assert is_ip_addr(ip)
        return ip

Так как db больше не будет ссылкой на flask.ext.sqlalchemy.SQLAlchemy(app), как я могу преобразовать мою модель, чтобы использовать только SQLAlchemy. Есть ли способ для двух приложений (один с Flask-SQLAlchemy другим с SQLAlchemy) для использования одной и той же базы данных?

Ответ 1

вы можете сделать это, чтобы заменить db.Model:

from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base
import sqlalchemy as sa

base = declarative_base()
engine = sa.create_engine(YOUR_DB_URI)
base.metadata.bind = engine
session = orm.scoped_session(orm.sessionmaker())(bind=engine)

# after this:
# base == db.Model
# session == db.session
# other db.* values are in sa.*
# ie: old: db.Column(db.Integer,db.ForeignKey('s.id'))
#     new: sa.Column(sa.Integer,sa.ForeignKey('s.id'))
# except relationship, and backref, those are in orm
# ie: orm.relationship, orm.backref
# so to define a simple model

class UserModel(base):
    __tablename__ = 'users' #<- must declare name for db table
    id = sa.Column(sa.Integer,primary_key=True)
    name = sa.Column(sa.String(255),nullable=False)

то для создания таблиц:

 base.metadata.create_all()

Ответ 2

В документации по sqlalchemy есть хороший учебник с примерами, которые звучат так, как вы хотите.

Показывает, как подключаться к БД, отображать, создавать схемы и запрашивать/сохранять в БД.

Ответ 3

Проверьте этот github.com/mardix/active-alchemy

Active-Alchemy - это агностическая оболочка для SQLAlchemy, которая делает ее очень простой в использовании, реализуя простую активную запись, например api, в то время как она все еще использует db.session под ней. Вдохновленный Flask-SQLAlchemy

Ответ 4

Flask (> 1.0) пытается предоставить помощники для обмена кодами между веб-приложением и интерфейсом командной строки; я лично думаю, что это может быть чище, легче и проще создавать библиотеки, не связанные с фляжкой, но вы можете проверить:

Ответ 5

Это не полностью отвечает на ваш вопрос, потому что он не удаляет зависимость от флэшей, но вы можете использовать SqlAlchemy в сценариях и тестах, просто не используя приложение Flask.

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData

test_app = Flask('test_app')
test_app.config['SQLALCHEMY_DATABASE_URI'] = 'database_uri'
test_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

metadata = MetaData(schema='myschema')
db = SQLAlchemy(test_app, metadata=metadata)

class IPEntry(db.Model):
    pass

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

def get_ipentry(db):
    class IPEntry(db.Model):
        pass
    return IPEntry

По мере того, как вы создаете время выполнения класса в функции, вы можете передавать разные экземпляры SqlAlchemy. Единственным недостатком является то, что вам нужно вызвать функцию для создания класса перед его использованием.

db = SqlAlchemy(...)
IpEntry = get_ipentry(db)
IpEntry.query.filter_by(id=123).one()

Ответ 7

Вот как использовать SQLAlchemy без Flask (например, для записи большого количества объектов в базу данных PostgreSQL):

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# Define variables DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAME   

SQLALCHEMY_DATABASE_URI = f'postgresql://{DB_USERNAME}:{DB_PASSWORD}@{DB_HOST}: 
{DB_PORT}/{DB_NAME}'

engine = create_engine(SQLALCHEMY_DATABASE_URI, echo=True)
Base = declarative_base()
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
Session.configure(bind=engine)
session = Session()

class MyModel(Base):
    __tablename__ = 'my_table_name'

    id = Column(Integer, primary_key=True)
    value = Column(String)

objects = [MyModel(id=0, value='a'), MyModel(id=1, value='b')]
session.bulk_save_objects(objects)
session.commit()