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
You should be initializing Admin
and registering views
and blueprints
inside create_app
. Check if this works for you.
# app factory
def create_app(config_name):
# configure current app
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# wrap app with extensions
...
# admin.init_app(app) does not work and flask-admin
# should be instantiated inside create_app()
# see https://github.com/flask-admin/flask-admin/issues/910#issuecomment-115003492
# for details
admin = Admin(app, name='MyAPP')
...
# import models
from .models.user import User
# more imports happening here
# import flask-admin views to be used in the admin panel
from .admin.views import MyView
# register admin view forms
admin.add_view(MyView(name='MyCustomView', endpoint='db'))
# register blueprints
# ...
# implementation of the app factory pattern
return app
EDIT:
What I believe is happening is that
admin
living in /adminflask-admin
in the app, but it clashes with the existing blueprintYou can achieve this doing two things:
blueprint
name in the repo to something different from admin
, since flask-admin
clashes with it. (Reading from your github issue it seems the are a lot of hardcoded internals for admin.static
, which makes changing the current admin
blueprint easier.the anatomy of a Blueprint is kinda like this
# app/myblueprint/__init__.py
from flask import Blueprint
# a random blueprint
myblueprint = Blueprint(name='mycustomblueprint',
import_name=__name__, # name of the file
static_folder='static', # a folder inside app/myblueprint/static
template_folder='templates', # a folder inside app/myblueprint/templates
static_url_path='/static', # this is what mycustomblueprint.static will point to, and if the name is admin it will be admin.static, thus colliding with flask-admin
url_prefix='/myblueprintprefix', # this will be appended to each view inside your blueprint, i.e. a view '/foo' will get converted into '/myblueprintprefix/foo' in your url mappings
subdomain=None,
url_defaults=None,
root_path=None)
from . import views # import the views inside app/myblueprint/views.py
then, you import it inside create_app
as
from .myblueprint import myblueprint as my_blueprint
app.register_blueprint(my_blueprint) # notice I've defined url_prefix in the Blueprint definition. You can do it at registration time, it's up to you
tl;dr: change the admin
blueprint since it's clashing with flask-admin
flask-admin
works based in views, and the pattern to generate admin views is by importing them and passing an url
parameter that gets appended to the /admin
endpoint (where flask-admin
lives).
In this case, you can think of two flavours (more but for the sake of the example it's okay)
ModelView
, which you use to create custom CRUD views and takes both a model
and a db.session
object. BaseView
which you use to extend a generic view inside the admin
blueprint used by flask-admin
. This means, if you want to render your own db.html
file inside the flask-admin
views, you have to do:
# app/modelviews/mycustomviews.py
from flask_admin import BaseView, expose
class DBView(BaseView): # notice I'm using BaseView and not ModelView
@expose('/')
def index(self):
return self.render('modelviews/db.html') # this file should live in app/templates/modelviews/db.html
and inside create_app
# register admin view forms
from .modelviews import DBView
admin.add_view(DBView(name='MyCustomView', endpoint='db')) # this will show up in your `flask-admin` main view as MyCustomView, and it will live in {host}/admin/db
You can also check in your url_map
parameter of the flask app in context that you have. You don't need this bit in your create_app
with app.app_context():
m =app.url_map
I mentioned it because it could help you debug your views inside the python repl
. Import your app, and follow the gist I've provided. The url_map
should return something like a list of
[ admin.index>,
dbview.index>]
This way you can confirm that your view lives where it should. Hope this helps.