【问题标题】:How can I create SQLAlchemy tables within __init__.py?如何在 __init__.py 中创建 SQLAlchemy 表?
【发布时间】:2016-10-02 03:18:34
【问题描述】:

我正在开发一个想要添加用户模型的应用程序。传统上应用程序是通过python3 runserver.py 启动的,但是我需要一个创建管理员的机制,所以我添加了这个功能:

def create_admin():
    username = input("Please enter username: ")
    # "select * from user where user.username = username;"
    q = db.session.query(User).filter(User.username == username)
    # if that user exists, don't create it
    if db.session.query(q.exists()).scalar():
        print("User already exists. Exiting.", file=sys.stderr)
        sys.exit(1)
    # otherwise, create it and commit to db
    password = getpass.getpass("Please enter password (it will not be echoed): ")
    admin = User(username, password=password, admin=True)
    db.session.add(admin)
    db.session.commit()

这将从项目foo 导入,其__init__.py 看起来像这样:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO
from flask.ext.login import LoginManager
import tempfile
import os

app = Flask(__name__)
sqllite_uri = os.path.join('sqlite:///{}'.format(tempfile.gettempdir()), 'test.db')
app.config['SQLALCHEMY_DATABASE_URI'] = sqllite_uri
db = SQLAlchemy(app)

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

socketio = SocketIO(app)

from foo.models import create_admin
from foo import views, models

问题是这些表是在runserver.py 中创建的,作为__main__ 的一部分,所以当我从命令行调用create_admin 时,这些表不存在。

我将db.create_all() 作为create_admin() 中的第一行,但如果我需要创建多个管理员,它会失败。这告诉我用户模型没有问题。此外,这使我认为在第一次导入 foo 时创建表会更好。

我尝试在db 对象在__init__.py 中创建后直接添加db.create_all(),但我的create_admin 调用仍然出现异常,因为我的用户表不存在。 db.create_all() 此时不知道这些表,这让我觉得我需要导入模型。

有没有办法在__init__.py 中创建我忽略的表?可能foo.model 中的表格在创建db 时没有出现,但我不知道如何导入__init__.py 中的模型。


编辑:我有一个解决方法,但我不喜欢它:

  1. python3 runsersever.py 创建表格
  2. ^C 退出
  3. 创建管理员...
  4. 重启服务器。
  5. ???
  6. 利润。

【问题讨论】:

    标签: python-3.x flask sqlalchemy flask-login


    【解决方案1】:

    我目前的解决方案:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_socketio import SocketIO
    from flask.ext.login import LoginManager
    import tempfile
    import os
    
    app = Flask(__name__)
    sqllite_uri = os.path.join('sqlite:///{}'.format(tempfile.gettempdir()), 'test.db')
    app.config['SQLALCHEMY_DATABASE_URI'] = sqllite_uri
    db = SQLAlchemy(app)
    
    login_manager = LoginManager()
    login_manager.init_app(app)
    login_manager.login_view = 'login'
    
    socketio = SocketIO(app)
    
    from foo.models import create_admin
    from foo import views, models
    
    db.create_all()
    

    解释:

    当我们准备好创建表时(即通过调用db.create_all()),所有表都是已知的,因为模型已从foo 导入。

    这可能不是这样做的惯用方式,但我将其发布给未来的用户。我仍然愿意接受更好的选择!

    【讨论】:

    • 为什么你觉得这不是惯用语?如果您希望在模型定义之后执行db.create_all(),那么最合乎逻辑的放置位置是在您导入模型定义之后。您希望 db.create_all() 出现在哪里?
    • @univerio 我对 python 比较陌生。我并没有说这不是惯用的,我只是发出警告以防万一。无论哪种方式,惯用的!= 合乎逻辑的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 2017-08-15
    • 1970-01-01
    • 2012-01-05
    • 2012-02-16
    • 2010-10-09
    相关资源
    最近更新 更多