[英]Flask-Admin Blueprint creation during Testing
我正在测试我的应用时,我在使用Flask-Admin创建蓝图时遇到了麻烦。
这是我的View类(使用SQLAlchemy)
##
# All views that only admins are allowed to see should inherit from this class.
#
class AuthView(ModelView):
def is_accessible(self):
return current_user.is_admin()
class UserView(AuthView):
column_list = ('name', 'email', 'role_code')
这是我初始化视图的方式:
# flask-admin
admin.add_view(UserView(User, db.session))
admin.init_app(app)
但是,当我尝试运行多个测试(故障总是发生在第二个测试和随后的所有其他测试)时,我总是收到以下错误消息:
======================================================================
ERROR: test_send_email (tests.test_views.TestUser)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/lib/python2.7/site-packages/nose/case.py", line 133, in run
self.runTest(result)
File "/lib/python2.7/site-packages/nose/case.py", line 151, in runTest
test(result)
File "/lib/python2.7/site-packages/flask_testing.py", line 72, in __call__
self._pre_setup()
File "/lib/python2.7/site-packages/flask_testing.py", line 80, in _pre_setup
self.app = self.create_app()
File "/tests/test_init.py", line 27, in create_app
app = create_app(TestConfig)
File "/fbone/app.py", line 41, in create_app
configure_extensions(app)
File "/fbone/app.py", line 98, in configure_extensions
admin.add_view(UserView(User, db.session))
File "/lib/python2.7/site-packages/flask_admin/base.py", line 484, in add_view
self.app.register_blueprint(view.create_blueprint(self))
File "/lib/python2.7/site-packages/flask/app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "/lib/python2.7/site-packages/flask/app.py", line 885, in register_blueprint
(blueprint, self.blueprints[blueprint.name], blueprint.name)
AssertionError: A blueprint's name collision occurred between <flask.blueprints.Blueprint object at 0x110576910> and <flask.blueprints.Blueprint object at 0x1103bd3d0>. Both share the same name "userview". Blueprints that are created on the fly need unique names.
奇怪的是,这只发生在第二次测试中,而且从未在我运行应用程序时发生。
当我调试测试时,它第一次完全按照我的预期执行,并在init_app(app)之后将蓝图添加到应用程序中。 第二次,当进入add_view步骤时,该过程立即停止(我认为这很奇怪,因为蓝图已在init_app(app)调用中注册?)
在使用Flask-Admin和使用pytest进行测试时,我发生了同样的事情。 通过将管理实例的创建移动到app工厂,我能够修复它,而无需为我的测试创建拆卸功能。
之前:
# extensions.py
from flask.ext.admin import Admin
admin = Admin()
# __init__.py
from .extensions import admin
def create_app():
app = Flask('flask_app')
admin.add_view(sqla.ModelView(models.User, db.session))
admin.init_app(app)
return app
后:
# __init__.py
from flask.ext.admin import Admin
def create_app():
app = Flask('flask_app')
admin = Admin()
admin.add_view(sqla.ModelView(models.User, db.session))
admin.init_app(app)
return app
因为pytest每次运行app工厂时都不再尝试在全局管理实例上注册多个视图。 这与典型的Flask扩展使用不一致,但它可以工作,它可以让您的应用工厂免受Flask-Admin视图的困扰。
我不得不将以下内容添加到我的测试用例tearDown中。 它清除了在测试设置中添加到管理扩展的视图
from flask.ext.testing import TestCase
from flask.ext.admin import BaseView
# My application wide instance of the Admin manager
from myapp.extensions import admin
class TestView(BaseView):
...
class MyTestCase(TestCase):
def setUp(self):
admin.add_view(TestView())
def tearDown(self):
admin._views.pop(-1)
admin._menu.pop(-1)
这肯定是一个黑客,但它在我遇到这个问题时完成了工作。
以防这对任何人都有帮助,另一种处理方法是:
class MyTestCase(TestCase):
def setUp(self):
admin._views = []
这样您就不必在工厂内设置Admin()初始化。 这对我来说似乎更合适。
它以这种方式运作。 仅供参考。
#YourApp/init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
db = SQLAlchemy()
admin = Admin(name='TuozhanOA', template_mode='bootstrap3')
def create_app(config_class=Config):
app = Flask(name)
app.config.from_object(Config)
db.init_app(app)
admin.init_app(app)
from YourApp.main.routes import main
app.register_blueprint(main)
from YourApp.adminbp.routes import adminbp, user_datastore
app.register_blueprint(adminbp)
security = Security(app, user_datastore)
return app
#YourApp/adminbp/routes.py
from flask import render_template, Blueprint
from YourApp.models import User, Role
from YourApp import db, admin
from flask_admin.contrib.sqla import ModelView
from wtforms.fields import PasswordField
from flask_admin.contrib.fileadmin import FileAdmin
import os.path as op
from flask_security import current_user, login_required, RoleMixin, Security,
SQLAlchemyUserDatastore, UserMixin, utils
adminbp = Blueprint('adminbp', name)
admin.add_view(ModelView(User, db.session, category="Team"))
admin.add_view(ModelView(Role, db.session, category="Team"))
path = op.join(op.dirname(file), 'tuozhan')
admin.add_view(FileAdmin(path, '/static/tuozhan/', name='File Explore'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.