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

У меня был небольшой веб-сервис, созданный с использованием 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) использовать одну и ту же базу данных?


person amccormack    schedule 08.05.2015    source источник
comment
база данных не должна зависеть от используемых вами моделей или уровня ORM.   -  person Makoto    schedule 08.05.2015
comment
Да, я понимаю. Я ищу способ повторного использования кода как во фляге, так и без фляги без необходимости существенного изменения определений моей модели.   -  person amccormack    schedule 08.05.2015
comment
В вашей модели нет ничего связанного с флягой. Все, что вам нужно, это создать соединение с базой данных и импортировать вашу модель либо во флягу, либо в приложение без фляги. Я бы просто поместил модель в «models.py» (на самом деле просто переместите вышеуказанное из основного файла .py фляги и при необходимости импортируйте/создайте экземпляр IPentry).   -  person GG_Python    schedule 09.05.2015


Ответы (7)


вы можете сделать это, чтобы заменить 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()
person Kyle Roux    schedule 16.05.2017

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

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

person Levon    schedule 16.07.2016

Вот как использовать 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}'

# ----- This is related code -----
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()
# ----- This is related code -----

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()
person Galina Alperovich    schedule 08.03.2019
comment
Не думаю, что вопрос был связан с объемными вставками - person Kyle Roux; 02.05.2019
comment
Массовая вставка @KyleRoux — это всего лишь простой пример создания воспроизводимого кода. Связанная часть — это 6 строк сверху, где я создаю движок. Я потратил довольно много времени, чтобы заставить его работать без Flask таким образом, поэтому не уверен, почему вы думаете, что это не имеет значения :/ - person Galina Alperovich; 06.05.2019
comment
Нашел это довольно полезным и компактным - person Francois; 03.12.2019

Есть отличная статья о Flask-SQLAlchemy: как это работает и как модифицировать модели, чтобы использовать их вне Flask:

http://derrickgilland.com/posts/demystifying-flask-sqlalchemy/

person maxkoryukov    schedule 25.10.2017
comment
Это отличная ссылка, но в настоящее время она не работает. https://web.archive.org/web/20190530064812/http://derrickgilland.com/posts/demystifying-flask-sqlalchemy/ может помочь - person Yehosef; 01.01.2020

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

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

person juzten    schedule 08.05.2015
comment
Однако следует обновить ссылку... docs.sqlalchemy.org/en/latest/ orm/tutorial.html - person Inego; 15.10.2018

Это не полностью отвечает на ваш вопрос, поскольку не удаляет зависимость от Flask, но вы можете использовать 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()
person Timo    schedule 26.07.2017

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

person bufh    schedule 03.06.2015
comment
Обе эти ссылки в настоящее время кажутся неработающими. - person holdenweb; 21.11.2018
comment
@holdenweb ‹ ссылки на официальную документацию исправлены, спасибо за сообщение - person bufh; 30.11.2018