我尝试从此示例Flask-Admin中分离代码:
https://github.com/flask-admin/flask-admin/blob/master/examples/auth/app.py
然而,当我添加更多代码时它变得很乱,所以我试图构造它们但是我得到一些错误,我认为是因为循环依赖。我可以运行主页和管理页面,但是当我尝试登录时出现了一些错误(例如admin:admin)。
__ init __。py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# create the Flask application
app = Flask(__name__)
app.config.from_pyfile('config.py')
db = SQLAlchemy(app)
headers = {'content-type': 'application/json'}
from myapp import app
应用。吡啶
import os
from flask import Flask, url_for, request, render_template, json, jsonify
from flask_security import Security, SQLAlchemyUserDatastore
from flask_security.utils import hash_password
import flask_admin, requests
from flask_admin import helpers as admin_helpers
from myapp import app, db, headers
from myapp.models import User, Role, MyModelView
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
# Initialize flask-migrate and script manager
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db.session, User, Role)
security = Security(app, user_datastore)
# Create admin
admin = flask_admin.Admin(
app,
'Administrator',
base_template='my_master.html',
template_mode='bootstrap3'
)
# Add model views
admin.add_view(MyModelView(Role, db.session))
admin.add_view(MyModelView(User, db.session))
# define a context processor for merging flask-admin's template context into the
# flask-security views.
@security.context_processor
def security_context_processor():
return dict(
admin_base_template=admin.base_template,
admin_view=admin.index_view,
h=admin_helpers,
get_url=url_for
)
def build_sample_db():
"""
Populate a small db with some example entries.
"""
import string
import random
db.drop_all()
db.create_all()
with app.app_context():
user_role = Role(name='user')
super_user_role = Role(name='superuser')
db.session.add(user_role)
db.session.add(super_user_role)
db.session.commit()
test_user = user_datastore.create_user(
first_name='Admin',
email='admin',
password=hash_password('admin'),
roles=[user_role, super_user_role]
)
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie', 'Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
last_names = [
'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
]
for i in range(len(first_names)):
tmp_email = first_names[i].lower() + "." + last_names[i].lower() + "@example.com"
tmp_pass = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10))
user_datastore.create_user(
first_name=first_names[i],
last_name=last_names[i],
email=tmp_email,
password=hash_password(tmp_pass),
roles=[user_role, ]
)
db.session.commit()
return
# Flask views
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/posts')
def getPosts():
response = requests.get('...some_url', headers=headers)
...some codes here
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet.
app_dir = os.path.realpath(os.path.dirname(__file__))
database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
# Start app
app.secret_key = 'secret_key'
app.run(debug=True)
# Start script manager
manager.run()
models.py
from flask import abort, redirect, url_for, request
from flask_security import UserMixin, RoleMixin, login_required, current_user
from flask_admin.contrib import sqla
from myapp import db
# 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))
def __str__(self):
return self.name
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(255))
last_name = db.Column(db.String(255))
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())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def __str__(self):
return self.email
# Create a user to test with
class MyModelView(sqla.ModelView):
def is_accessible(self):
if not current_user.is_active or not current_user.is_authenticated:
return False
if current_user.has_role('superuser'):
return True
return False
def _handle_view(self, name, **kwargs):
"""
Override builtin _handle_view in order to redirect users when a view is not accessible.
"""
if not self.is_accessible():
if current_user.is_authenticated:
# permission denied
abort(403)
else:
# login
return redirect(url_for('security.login', next=request.url))
我还有一个单独的配置文件。这就是我得到的错误:
2017-09-12 14:32:37,285 INFO sqlalchemy.engine.base.Engine SELECT user.id AS user_id, user.first_name AS user_first_name, user.last_name AS user_last_name, user.email AS user_email, user.password AS user_password, user.active AS user_active, user.confirmed_at AS user_confirmed_at
FROM user
WHERE lower(user.email) = lower(%s)
LIMIT %s
2017-09-12 14:32:37,285 INFO sqlalchemy.engine.base.Engine ('admin', 1)
2017-09-12 14:32:37,312 INFO sqlalchemy.engine.base.Engine SELECT `role`.id AS role_id, `role`.name AS role_name, `role`.description AS role_description
FROM `role`, roles_users
WHERE %s = roles_users.user_id AND `role`.id = roles_users.role_id
2017-09-12 14:32:37,312 INFO sqlalchemy.engine.base.Engine (1L,)
[2017-09-12 14:32:37,314] ERROR in app: Exception on /admin/login/ [POST]
Traceback (most recent call last):
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask/app.py", line 1615, in full_dispatch_request
return self.finalize_request(rv)
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask/app.py", line 1632, in finalize_request
response = self.process_response(response)
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask/app.py", line 1856, in process_response
response = handler(response)
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask_security/views.py", line 58, in _commit
_datastore.commit()
File "/home/.../myapp/venv/local/lib/python2.7/site-packages/flask_security/datastore.py", line 31, in commit
self.db.session.commit()
AttributeError: 'scoped_session' object has no attribute 'session'
2017-09-12 14:32:37,314 INFO sqlalchemy.engine.base.Engine ROLLBACK
127.0.0.1 - - [12/Sep/2017 14:32:37] "POST /admin/login/ HTTP/1.1" 500 -
答案 0 :(得分:0)
好的,为避免任何循环依赖性问题,请将扩展程序移至 extensions.py 文件,如下所示:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
migrate = Migrate()
manager = Manager()
然后在 app.py 中,以便在创建实例后绑定扩展程序(之后甚至可以执行此操作)
if __name__ == "__main__":
否则,
from extensions import db, migrate, manager
app = Flask(__name__)
db.init_app(app)
migrate.init_app(app, db)
manager.init_app(app)
manager.add_command('db', MigrateCommand)
&安培;为了更好地理解你的错误,你可以阅读有关flask-sqlalchemy扩展(here)以及sqlalchemy会话,烧瓶会话和放大器之间的区别。如何使两者与范围会话(here)
进行交互