Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot use current_user in jinja2 macro?

I use Flask-Login which provides the current_user object in templates. I want to write a macro to show a comment form or a log in link depending on if the user is logged in. If I use this code directly in the template, it works:

{% if current_user.is_authenticated %}
    {{ quick_form(form) }}
{% else %}
    <a href="{{ url_for('auth.login') }}">Log In with Github</a>
{% endif %}

I placed the same code in a macro and import the macro in my template.

{% macro comment_form(form) %}
    {% if current_user.is_authenticated %}
        ...
    {% endif %}
{% endmacro %}
{% from "macros/comments.html" import comment_form %}
{% extends "base.html" %}
{% block content %}
    {# ... content goes here ... #}
    {{ comment_form(form) }}
{% endblock %}

When I try to load this page, the error I get is:

jinja2.exceptions.UndefinedError: 'current_user' is undefined

Of course, the easy workaround is to pass in current_user as a parameter and use that (making the signature comment_form(user, form)), although this is a fairly ugly solution (imo).

Why doesn't the macro use the context processor? Does it not hold the context?

like image 642
corvid Avatar asked Oct 13 '14 12:10

corvid


3 Answers

The context a template is rendered in is not passed to imports unless instructed to do so. See the relevant docs.

You're right, you don't need to inject context as arguments to macros. You can import the macros with context and they will have access the the context of the template they're imported in.

{% from "macros/comments.html" import comment_form with context %}
like image 148
davidism Avatar answered Sep 21 '22 09:09

davidism


The current_user.is_authenticated is now accessed as a property and calling the method definition will lead to problems with more up-to-date library versions.

See: https://flask-login.readthedocs.org/en/latest/#flask.ext.login.current_user

like image 20
MrMesees Avatar answered Sep 21 '22 09:09

MrMesees


UPDATE: This is an incorrect answer according to OP's requirements.

According to jinja2 docs not every variable is available in jinja2 macros. Change your macro and send ’current_user’ as a parameter to it:

% macro comment_form(form, current_user, disabled=False) %}
{% if current_user.is_authenticated() %}
  {{ quick_form(form) }}
{% else %}
  <p class="text-muted">You are not signed in. Please <a href="{{ url_for('auth.login') }}">Sign In With Github</a> to continue
  </p>
{% endif %}
{% endmacro %}

and this is how your will use it:

{% from "macros/comments.html" import comment_form %}
{% extends "base.html" %}
{% block content %}
  {# ... content goes here ... #}
  {{ comment_form(form, current_user) }}
{% endblock %}
like image 1
mehdix Avatar answered Sep 24 '22 09:09

mehdix