world hello deploy app python nginx flask jinja2 uwsgi

python - hello - UndefinedError: ''usuario'' no está definido



flask production gunicorn (2)

Actualmente estoy desarrollando una aplicación Flask (lo he estado haciendo durante el año pasado) y me encuentro con un ... extraño error. Tengo algunos archivos que siempre están incluidos en mis plantillas Jinja2 (barras de navegación), y usan el nombre y el avatar de los usuarios. Como consecuencia, cada vez que renderizo una plantilla, la paso al usuario. Recientemente noté un error en mi servidor de prod:

<img alt="image" class="img-circle" src="{{ user.image }}" style="width: 48px;"/> File "/usr/local/lib/python2.7/dist-packages/jinja2/environment.py", line 397, in getattr return getattr(obj, attribute) jinja2.exceptions.UndefinedError: ''user'' is undefined

Esto está en una de mis barras de navegación. El método que hace que esta plantilla use esto:

@mod.route(''/broken_pus'', methods=[''POST'', ''GET'']) def view_broken_pus(): return render_template("view_broken_pus.html", user=g.user, urls_for_active_clients=DeletedURLs.objects()[0].urls_for_active_clients, other_urls=DeletedURLs.objects()[0].other_urls)

Como puede ver, paso el usuario = g.user. Hago esto en cada vista de mi sitio web. Y funciona en todas partes, EXCEPTO en este método, que es bastante pequeño. Tengo muchas otras rutas como esa, con solo una plantilla de renderizado, así que no entiendo cuál es el problema.

También lo obtengo en otro método, más grande, que siempre funcionó antes:

@mod.route(''/users/add'', methods=[''GET'', ''POST'']) @requires_roles("admin", "project-leader") def add(): """ Method adding a new user. """ # We do not use WTForms there since we need custom checkboxes for the role # Instead we use basic HTML and treat the checkboxes here if request.method == ''POST'': user = User(name=request.form.get(''name''), email=request.form.get(''email'')) l = [] # big switch assignement user.role = l try: user.save() except errors.NotUniqueError: flash(u''User %s already in database.'' % user.name, ''danger'') return redirect(url_for(''home'')) flash(u''User %s registered.'' % user.name, ''success'') return redirect(url_for(''home'')) return render_template(''add_user.html'', page=url_for(''users.add''), user=g.user, clients=Client.objects())

Cuando primero carga el formulario para agregar un usuario, funciona. Cuando lo agrego, por alguna razón, obtengo el error (y el usuario no se guarda en la base de datos).

Como esto funciona perfectamente en local, estoy empezando a sospechar un problema en el servidor de producción. Usamos nginx y uwsgi para la aplicación, y recientemente implementé algunas tareas de apio. ¿Tienes alguna idea?

Gracias por adelantado.


Echa un vistazo a la fuente del matraz para render_template :

Simplemente llama a template.render(context) , pero después de la llamada a before_render_template.send(app, template=template, context=context)

A partir de esto, creo que hay algún controlador before_render_template , que modifica el contexto instalado.

Para depurar esto, puedo intentar llamar a algo como esto:

from flask import app @mod.route(''/broken_pus'', methods=[''POST'', ''GET'']) def view_broken_pus(): template = app.jinja_env.get_or_select_template("view_broken_pus.html") return template.render(dict( user=g.user, urls_for_active_clients=DeletedURLs.objects()[0].urls_for_active_clients, other_urls=DeletedURLs.objects()[0].other_urls, ))

Si esto funciona, tendré que before_render_template quién modifica el contexto en el slot before_render_template .


Sospecho que se está enhebrando. Si g es algún tipo de referencia global, entonces es posible que deba asegurarse de que esté configurado en threading.local o que los bloqueos de subprocesamiento se utilicen para garantizar que ningún subproceso se pueda apropiar de g.user antes de que otro ''otro'' subproceso lo ataque. .

Vea cómo hacer que un administrador de contexto de python 2.7 sea seguro para una forma de manejar ''globales'' sin sacrificar la seguridad de los hilos.