I'm trying to extend the flask-base project https://github.com/hack4impact/flask-base/tree/master/app. This uses the the application factory pattern in app/init.py and blueprints.
In the app/init.py I have:
import os from flask import Flask from flask_mail import Mail from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager from flask_assets import Environment from flask_wtf import CsrfProtect from flask_compress import Compress from flask_rq import RQ from flask_admin import Admin, BaseView, expose from flask_admin.contrib.sqla import ModelView # from app.models import User from config import config from .assets import app_css, app_js, vendor_css, vendor_js basedir = os.path.abspath(os.path.dirname(__file__)) mail = Mail() db = SQLAlchemy() csrf = CsrfProtect() compress = Compress() # Set up Flask-Login login_manager = LoginManager() login_manager.session_protection = 'strong' login_manager.login_view = 'account.login' from app.models import User def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # not using sqlalchemy event system, hence disabling it with app.app_context(): m =app.url_map config[config_name].init_app(app) # Set up extensions mail.init_app(app) db.init_app(app) login_manager.init_app(app) csrf.init_app(app) compress.init_app(app) RQ(app) # adm = Admin(app, name='MyAPP') adm = Admin(endpoint='adminz', name='adz', url='/adminz') ...... # Create app blueprints from .main import main as main_blueprint app.register_blueprint(main_blueprint) from .account import account as account_blueprint app.register_blueprint(account_blueprint, url_prefix='/account') from .admin import admin as admin_blueprint # from .admin import admin_blueprint app.register_blueprint(admin_blueprint, url_prefix='/admin') return app
templates/admin/db.html:
<p>Hello world</p>
To the admin views (https://github.com/hack4impact/flask-base/blob/master/app/admin/views.py) I've added :
from flask_admin import Admin, BaseView, expose from flask_admin.contrib.sqla import ModelView from app import adm as adm, db class MyView(ModelView): @expose('/') def db(self): return self.render('admin/db.html') # admin management setup @main.route('/db') def db(): adm.add_view(MyView(User, db.session))
I'm getting the admin dashboard not the flask-admin basic view when I open:
127.0.0.1:5000/db
What am I doing wrong?
EDIT:
following your directions I changed create_app to start with:
def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # not using sqlalchemy event system, hence disabling it # adm = Admin(name='admin2', endpoint='/db', url='/db', template_mode='bootstrap3',base_template='admin/db.html') config[config_name].init_app(app) # Set up extensions mail.init_app(app) db.init_app(app) login_manager.init_app(app) csrf.init_app(app) compress.init_app(app) RQ(app) adm = Admin(app, name='MyAPP') # adm = Admin(endpoint='adminz', name='adz', url='/adminz') adm.add_view(MyView(User, db.session, endpoint='db'))
This results in :
File "....flask\app.py", line 946, in register_blueprint (blueprint, self.blueprints[blueprint.name], blueprint.name) AssertionError: A blueprint's name collision occurred between and . Both share the same name "admin". Blueprints that are created on the fly need unique names.
EDIT2:
to the end of create_app I've added:
# Create app blueprints from .main import main as main_blueprint app.register_blueprint(main_blueprint) from .account import account as account_blueprint app.register_blueprint(account_blueprint, url_prefix='/account') from .admin import admin as admin_blueprint # from .admin import admin_blueprint app.register_blueprint(admin_blueprint, url_prefix='/admin') # app.register_blueprint(admin_blueprint, url_prefix='/ab') with app.app_context(): m =app.url_map return app
I'm not sure what you want to see but m.rules gives:
<Rule '/account/manage/change-password' (HEAD, GET, OPTIONS, POST) -> account.change_password>, <Rule '/account/manage/change-email' (HEAD, GET, OPTIONS, POST) -> account.change_email_request>, <Rule '/account/manage/info' (HEAD, GET, OPTIONS, POST) -> account.manage>, <Rule '/account/confirm-account' (HEAD, GET, OPTIONS) -> account.confirm_request>, <Rule '/account/reset-password' (HEAD, GET, OPTIONS, POST) -> account.reset_password_request>, <Rule '/account/unconfirmed' (HEAD, GET, OPTIONS) -> account.unconfirmed>, <Rule '/account/register' (HEAD, GET, OPTIONS, POST) -> account.register>, <Rule '/account/logout' (HEAD, GET, OPTIONS) -> account.logout>, <Rule '/account/manage' (HEAD, GET, OPTIONS, POST) -> account.manage>, <Rule '/account/login' (HEAD, GET, OPTIONS, POST) -> account.login>, <Rule '/admin/_update_editor_contents' (OPTIONS, POST) -> admin.update_editor_contents>, <Rule '/admin/invite-user' (HEAD, GET, OPTIONS, POST) -> admin.invite_user>, <Rule '/admin/new-user' (HEAD, GET, OPTIONS, POST) -> admin.new_user>, <Rule '/admin/users' (HEAD, GET, OPTIONS) -> admin.registered_users>, <Rule '/get_session_job_value' (HEAD, GET, OPTIONS) -> main.get_session_job_value>, <Rule '/cl_confirm_chrome' (HEAD, GET, OPTIONS, POST) -> main.cl_confirm_chrome>, <Rule '/render_png' (HEAD, GET, OPTIONS) -> main.render_png>, <Rule '/selected' (HEAD, GET, OPTIONS) -> main.selected>, <Rule '/cl_dash' (HEAD, GET, OPTIONS, POST) -> main.cl_dash>, <Rule '/about' (HEAD, GET, OPTIONS) -> main.about>, <Rule '/admin/' (HEAD, GET, OPTIONS) -> admin.index>, <Rule '/dash' (HEAD, GET, OPTIONS) -> main.dash>, <Rule '/jobs' (HEAD, GET, OPTIONS) -> main.get_jobs>, <Rule '/' (HEAD, GET, OPTIONS) -> main.index>, <Rule '/account/manage/change-email/<token>' (HEAD, GET, OPTIONS, POST) -> account.change_email>, <Rule '/admin/user/<user_id>/change-account-type' (HEAD, GET, OPTIONS, POST) -> admin.change_account_type>, <Rule '/admin/user/<user_id>/change-email' (HEAD, GET, OPTIONS, POST) -> admin.change_user_email>, <Rule '/admin/user/<user_id>/_delete' (HEAD, GET, OPTIONS) -> admin.delete_user>, <Rule '/admin/user/<user_id>/delete' (HEAD, GET, OPTIONS) -> admin.delete_user_request>, <Rule '/admin/user/<user_id>/info' (HEAD, GET, OPTIONS) -> admin.user_info>, <Rule '/account/join-from-invite/<user_id>/<token>' (HEAD, GET, OPTIONS, POST) -> account.join_from_invite>, <Rule '/account/confirm-account/<token>' (HEAD, GET, OPTIONS) -> account.confirm>, <Rule '/account/reset-password/<token>' (HEAD, GET, OPTIONS, POST) -> account.reset_password>, <Rule '/admin/static/<filename>' (HEAD, GET, OPTIONS) -> admin.static>, <Rule '/admin/user/<user_id>' (HEAD, GET, OPTIONS) -> admin.user_info>, <Rule '/results/<job_key>' (HEAD, GET, OPTIONS) -> main.get_results>, <Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>
EDIT 3:
I have to say that is an incredible answer! You have really taught me a lot. I have replaced the urls with the rules above following your directions. My original plan 10 days ago was just to use the basic flask-admin CRUD functionality. I'm not interested in the db.html template (its just something I tried).
anyway trying to change the name of the admin blueprint ( your number 1). I had tried this before changing app/admin/init.py to :
from flask import Blueprint admin = Blueprint('admin_blueprint', __name__) from . import views # noqa
Now when I open
http://127.0.0.1:5000/adminz/
I get a 404 error
FINAL EDIT:
The problem was solved by https://chat.stackoverflow.com/users/5819113/diego-quintana who explained that there was a conflict between flask-admin which creates a blueprint and the flask-base admin blueprint. By changing both the name of the blueprint and the static file folder of the flask-base project. Flask-admin could work without being overridden. Please see https://github.com/kc1/flask-base