example python flask-sqlalchemy flask flask-admin

python - flask blueprint example



Creación de Blueprint de Flask-Admin durante la prueba (3)

Tuve que agregar lo siguiente a mi caso de prueba tearDown. Limpia las vistas que se agregaron a la extensión de administrador en la configuración de prueba

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)

Esto es ciertamente un truco, pero hizo el trabajo mientras tuve este problema.

Estoy teniendo problemas con la creación de planos por Flask-Admin cuando estoy probando mi aplicación.

Esta es mi clase de Vista (usando 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'')

Así es como inicializo las vistas:

# flask-admin admin.add_view(UserView(User, db.session)) admin.init_app(app)

Sin embargo, cuando trato de ejecutar más de una prueba (la falla siempre ocurre en la segunda prueba y todas las otras pruebas que siguen), siempre recibo el siguiente mensaje de error:

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

Lo extraño es que esto solo sucede en la segunda prueba y nunca cuando solo ejecuto la aplicación.

Cuando depuré las pruebas, la primera vez hice exactamente lo que esperaba y agregué el blueprint a la aplicación después de la init_app (aplicación). La segunda vez, sin embargo, el proceso se detuvo inmediatamente al alcanzar el paso add_view (que creo que es extraño porque los blueprints se registran en la llamada init_app (app)?)


Me pasó lo mismo al usar Flask-Admin y probar con Pytest. Pude solucionarlo sin crear funciones de extracción para mis pruebas al mover la creación de la instancia de administración a la fábrica de aplicaciones.

Antes de:

# 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

Después:

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

Porque pytest ejecuta la fábrica de aplicaciones cada vez que ya no intenta registrar múltiples vistas en una instancia de administración global. Esto no es coherente con el uso habitual de la extensión de Flask, pero funciona y evitará que su fábrica de aplicaciones tropiece con las vistas de Flask-Admin.


En caso de que esto ayude a alguien, otra forma de manejar esto es hacer:

class MyTestCase(TestCase): def setUp(self): admin._views = []

de esta manera no tiene que configurar la inicialización de Admin () dentro de la fábrica. Me parece más apropiado.