简体   繁体   English

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

[英]Using Flask-SQLAlchemy without Flask

I had a small web service built using Flask and Flask-SQLAlchemy that only held one model. I now want to use the same database, but with a command line app, so I'd like to drop the Flask dependency.我有一个使用FlaskFlask-SQLAlchemy构建的小型 web 服务,它只包含一个 model。我现在想使用相同的数据库,但使用命令行应用程序,所以我想删除Flask依赖项。

My model looks like this:我的 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

Since db will no longer be a reference to flask.ext.sqlalchemy.SQLAlchemy(app) , how can I convert my model to use just SQLAlchemy. Is there a way for the two applications (one with Flask-SQLAlchemy the other with SQLAlchemy ) to use the same database?由于db将不再是对flask.ext.sqlalchemy.SQLAlchemy(app)的引用,我如何将我的 model 转换为仅使用 SQLAlchemy。这两个应用程序有没有办法(一个使用Flask-SQLAlchemy ,另一个使用SQLAlchemy )8494使用相同的数据库?

you can do this to replace db.Model :你可以这样做来替换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)

then to create the tables:然后创建表:

 base.metadata.create_all()

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

Active-Alchemy is a framework agnostic wrapper for SQLAlchemy that makes it really easy to use by implementing a simple active record like api, while it still uses the db.session underneath. Active-Alchemy 是 SQLAlchemy 的框架无关包装器,它通过实现一个简单的活动记录(如 api)使其非常易于使用,同时它仍然使用下面的 db.session。 Inspired by Flask-SQLAlchemy受 Flask-SQLAlchemy 的启发

That is how to use SQLAlchemy without Flask (for example to write a bulk of objects to PostgreSQL database):这就是如何在没有 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()

The sqlalchemy docs has a good tutorial with examples that sound like what you want to do. sqlalchemy docs 有一个很好的教程,里面的例子听起来像你想要做的。

Shows how to connect to a db, mapping, schema creation, and querying/saving to the db.展示如何连接到数据库、映射、模式创建以及查询/保存到数据库。

There is a great article about Flask-SQLAlchemy: how it works, and how to modify models to use them outside of Flask:有一篇关于 Flask-SQLAlchemy 的很棒的文章:它是如何工作的,以及如何修改模型以在 Flask 之外使用它们:

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

Flask (> 1.0) attempt to provide helpers for sharing code between an web application and a command line interface; Flask (> 1.0) 尝试提供帮助器以在 Web 应用程序和命令行界面之间共享代码; i personally think it might be cleaner, lighter and easier to build libraries unbound to flask, but you might want to check:我个人认为构建未绑定到烧瓶的库可能更干净、更轻、更容易,但您可能需要检查:

This does not completely answer your question, because it does not remove Flask dependency, but you can use SqlAlchemy in scripts and tests by just not running the Flask app.这并不能完全回答您的问题,因为它不会删除 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

One difficulty you may encounter is the requirement of using db.Model as a base class for your models if you want to target the web app and independent scripts using same codebase.您可能会遇到的一个困难是,如果您想使用相同的代码库来定位 Web 应用程序和独立脚本,则需要使用db.Model作为模型的基类。 Possible way to tackle it is using dynamic polymorphism and wrap the class definition in a function.解决它的可能方法是使用动态多态并将类定义包装在一个函数中。

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

As you construct the class run-time in the function, you can pass in different SqlAlchemy instances.当您在函数中构造类运行时,您可以传入不同的SqlAlchemy实例。 Only downside is that you need to call the function to construct the class before using it.唯一的缺点是在使用之前需要调用函数来构造类。

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

Create database and table创建数据库和表

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)

Using Flask_SQLAlchemy directly直接使用 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