繁体   English   中英

在没有 Flask 的情况下使用 Flask-SQLAlchemy

[英]Using Flask-SQLAlchemy without Flask

我有一个使用FlaskFlask-SQLAlchemy构建的小型 web 服务,它只包含一个 model。我现在想使用相同的数据库,但使用命令行应用程序,所以我想删除Flask依赖项。

我的 model 看起来像这样:

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)的引用,我如何将我的 model 转换为仅使用 SQLAlchemy。这两个应用程序有没有办法(一个使用Flask-SQLAlchemy ,另一个使用SQLAlchemy )8494使用相同的数据库?

你可以这样做来替换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()

检查这个github.com/mardix/active-alchemy

Active-Alchemy 是 SQLAlchemy 的框架无关包装器,它通过实现一个简单的活动记录(如 api)使其非常易于使用,同时它仍然使用下面的 db.session。 受 Flask-SQLAlchemy 的启发

这就是如何在没有 Flask 的情况下使用 SQLAlchemy(例如将大量对象写入 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()

sqlalchemy docs 有一个很好的教程,里面的例子听起来像你想要做的。

展示如何连接到数据库、映射、模式创建以及查询/保存到数据库。

有一篇关于 Flask-SQLAlchemy 的很棒的文章:它是如何工作的,以及如何修改模型以在 Flask 之外使用它们:

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

Flask (> 1.0) 尝试提供帮助器以在 Web 应用程序和命令行界面之间共享代码; 我个人认为构建未绑定到烧瓶的库可能更干净、更轻、更容易,但您可能需要检查:

这并不能完全回答您的问题,因为它不会删除 Flask 依赖项,但是您可以通过不运行Flask 应用程序在脚本和测试中使用SqlAlchemy

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

您可能会遇到的一个困难是,如果您想使用相同的代码库来定位 Web 应用程序和独立脚本,则需要使用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()

创建数据库和表

import os

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

if os.path.exists('test.db'):
    os.remove('test.db')

Base = declarative_base()


class Person(Base):
    __tablename__ = 'person'

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


engine = create_engine('sqlite:///test.db')
Base.metadata.create_all(engine)

直接使用 Flask_SQLAlchemy

from flask import Flask
from sqlalchemy import MetaData
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String

app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app, metadata=MetaData())


class Person(db.Model):
    __tablename__ = 'person'

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


person = Person(name='Bob')
db.session.add(person)
db.session.commit()
print(person.id)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM