Неправильная панель инструментов при добавлении flask-admin в проект - PullRequest
0 голосов
/ 28 апреля 2018

enter image description here

Я пытаюсь расширить базовый проект колбы https://github.com/hack4impact/flask-base/tree/master/app. При этом используется шаблон фабрики приложений в app / init.py и blueprints.

В приложении / init.py у меня есть:

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

шаблоны / админ / db.html:

<p>Hello world</p>

К просмотру администратора (https://github.com/hack4impact/flask-base/blob/master/app/admin/views.py) Я добавил:

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))

Когда я открываю, я получаю панель администратора, а не базовый вид фляги-администратора:

 127.0.0.1:5000/db

enter image description here

Что я делаю не так?

EDIT:

следуя вашим указаниям, я изменил create_app для начала:

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'))

В результате:

Файл ".... flask \ app.py", строка 946, в register_blueprint (blueprint, self.blueprints [blueprint.name], blueprint.name) AssertionError: Столкновение имени проекта произошло между и. Оба имеют одно и то же имя «админ». Чертежи, созданные на лету, требуют уникальных имен.

EDIT2:

к концу create_app я добавил:

# 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

Я не уверен, что вы хотите увидеть, но m.rules дает:

 <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>

РЕДАКТИРОВАТЬ 3:

Я должен сказать, что это невероятный ответ! Вы действительно многому меня научили. Я заменил URL с правилами выше, следуя вашим указаниям. Мой первоначальный план 10 дней назад состоял в том, чтобы просто использовать базовую функциональность CRUD от flask-admin. Мне не интересен шаблон db.html (я просто попробовал его).

В любом случае пытаюсь сменить имя администратора (ваш номер 1). Я пробовал это перед изменением app / admin / init.py на:

from flask import Blueprint
admin = Blueprint('admin_blueprint', __name__)
from . import views  # noqa

Теперь, когда я открываю

http://127.0.0.1:5000/adminz/

Я получаю ошибку 404

ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ:

Проблема была решена https://chat.stackoverflow.com/users/5819113/diego-quintana, который объяснил, что существует конфликт между flask-admin, который создает проект и blueb-base администраторский проект. Путем изменения как имени проекта, так и статической папки с файлами проекта на базе фляги. Flask-admin может работать без переопределения. Пожалуйста, смотрите https://github.com/kc1/flask-base

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вы должны инициализировать Admin и зарегистрировать views и blueprints внутри create_app. Проверьте, работает ли это для вас.

# 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:

Я верю, что происходит то, что

  • У приложения в репозитории уже есть проект с именем admin, проживающий в / admin
  • Вы хотите внедрить flask-admin в приложение, но оно конфликтует с существующим планом

Вы можете достичь этого, сделав две вещи:

  1. Измените текущее имя blueprint в репо на другое, отличное от admin, так как flask-admin конфликтует с ним. (Читая из вашей проблемы с GitHub, кажется, что существует множество жестко закодированных внутренних элементов для admin.static, что делает изменение текущего admin blueprint проще .

Анатомия Светокопии выглядит примерно так

# 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

затем вы импортируете его внутрь create_app как

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: изменить шаблон admin, поскольку он конфликтует с flask-admin

  1. flask-admin работает на основе представлений, и шаблон для генерации представлений администратора заключается в импорте их и передаче параметра url, который добавляется к конечной точке /admin (где живет flask-admin) ). В этом случае вы можете подумать о двух вкусах (больше, но для примера все в порядке)
    • ModelView, который используется для создания пользовательских представлений CRUD и принимает как model, так и db.session объект.
    • BaseView, который вы используете для расширения общего вида внутри admin проекта, используемого flask-admin.

Это означает, что если вы хотите отобразить свой собственный db.html файл внутри flask-admin представлений, вам нужно сделать:

# 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

и внутри 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

Вы также можете проверить свой параметр url_map приложения колбы в контексте, который у вас есть. Вам не нужен этот бит в вашем create_app

with app.app_context():
m =app.url_map

Я упоминал об этом, потому что это может помочь вам отладить ваши взгляды внутри питона repl. Импортируйте свое приложение и следуйте предложенной мной сути. url_map должен возвращать что-то вроде списка <Rules>

 [<Rule '/admin/' (OPTIONS, HEAD, GET) -> admin.index>,
 <Rule '/admin/db' (OPTIONS, HEAD, GET) -> dbview.index>]

Таким образом, вы можете подтвердить, что ваш взгляд живет там, где и должен. Надеюсь, это поможет.

0 голосов
/ 28 апреля 2018

Используйте url вместо endpoint

adm = Admin(name='test',url='/db')
...