Я пытаюсь заставить базовое приложение Flask-Security работать с Flask-Migrate. У меня есть два основных файла py: app.py и db_migrate.py.
app.py:
from flask import Flask, render_template, request, session
from flask.ext.babel import Babel
from flask.ext.mail import Mail
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
import os
basedir = os.path.abspath(os.path.dirname(__file__)) #should be __ file __ with no spaces
# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.db')
app.config['DEFAULT_MAIL_SENDER'] = '[email protected]'
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_CONFIRMABLE'] = True
app.config['SECURITY_RECOVERABLE'] = True
app.config.from_object('config.email')
# Setup mail extension
mail = Mail(app)
# Setup babel
babel = Babel(app)
@babel.localeselector
def get_locale():
override = request.args.get('lang')
if override:
session['lang'] = override
rv = session.get('lang', 'en')
return rv
# Create database connection object
db = SQLAlchemy(app)
# Setup Flask-Security
from db_manager import User, Role #THIS IS PROBABLY WRONG!
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
#db.create_all()
# Views
@app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
db_migrate.py:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
import os
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.db')
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
# Define models
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
favcolor = db.Column(db.String(255))
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def __str__(self):
return '<User id=%s email=%s>' % (self.id, self.email)
if __name__ == '__main__':
manager.run()
Я запустил инструмент миграции, чтобы инициализировать и перенести базу данных один раз, чтобы создать новую базу данных, и это сработало:
python db_manager.py db init
python db_manager.py db migrate
Я попытался запустить app.py. Он правильно работает на локальном хосте, но затем, когда я пытаюсь войти в систему, я получаю следующую ошибку OperationalError:
OperationalError: (OperationalError) нет такой таблицы: пользователь u'SELECT user.id КАК user_id, user.email КАК user_email, user.password КАК user_password, user.active КАК user_active, user.confirmed_at КАК user_confirmed_at, user.favcolor КАК user_favcolor \nFROM пользователь \nГДЕ ниже(user.email) НРАВИТСЯ ниже(?)\n ПРЕДЕЛ ? КОМПЕНСИРОВАТЬ ?' (u'[email protected]', 1, 0)
По сути, я сомневаюсь, что правильно создаю user_datastore
и security
, поскольку мне, вероятно, не следует импортировать User
и Role
таким образом, но я не уверен, как правильно получить к ним доступ.
РЕДАКТИРОВАТЬ:
Я добавил эту последнюю команду, благодаря предложению:
python db_manager.py db ugrade
Но теперь я получаю эту ошибку, когда пытаюсь подтвердить регистрацию пользователя по электронной почте:
(InvalidRequestError: Object '' is already attached to session '1' (this is '3')