python - How to separate Flask-Admin (auth example) into different files with imports -
i tried separating codes sample flask-admin:
https://github.com/flask-admin/flask-admin/blob/master/examples/auth/app.py
however, becomes messy add more codes tried structure them i'm getting errors think because of circular dependencies. can run homepage , admin page, errors when tried sign in (e.g. admin:admin).
__init__.py
from flask import flask flask_sqlalchemy import sqlalchemy # create flask application app = flask(__name__) app.config.from_pyfile('config.py') db = sqlalchemy(app) headers = {'content-type': 'application/json'} myapp import app
app. py
import os flask import flask, url_for, request, render_template, json, jsonify flask_security import security, sqlalchemyuserdatastore flask_security.utils import hash_password import flask_admin, requests flask_admin import helpers admin_helpers myapp import app, db, headers myapp.models import user, role, mymodelview flask_script import manager flask_migrate import migrate, migratecommand # initialize flask-migrate , 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 context processor merging flask-admin's template context # 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 small db example entries. """ import string import random db.drop_all() db.create_all() 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' ] 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) 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 sample db on fly, if 1 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 flask_security import usermixin, rolemixin, login_required, current_user flask_admin.contrib import sqla 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 user test 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 redirect users when view 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))
i have separate config file. , error get:
2017-09-12 14:32:37,285 info sqlalchemy.engine.base.engine select user.id user_id, user.first_name user_first_name, user.last_name user_last_name, user.email user_email, user.password user_password, user.active user_active, user.confirmed_at user_confirmed_at user 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 role_id, `role`.name role_name, `role`.description role_description `role`, roles_users %s = roles_users.user_id , `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 -
okay, avoid circular dependency issues, move extensions extensions.py file, so:
from flask_sqlalchemy import sqlalchemy db = sqlalchemy() flask_script import manager flask_migrate import migrate, migratecommand migrate = migrate() manager = manager()
and in app.py bind extensions after creation of instance (you after)
if __name__ == "__main__":
else,
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)
& better understand error, read flask-sqlalchemy extension (here) , difference between sqlalchemy session, flask session & how make 2 interact scoped sessions(here)
Comments
Post a Comment