1

In every page (base.html), I want to check whether request.user has an administrator role from my class UserTypes and show the admin link. Currently I do something like this:

{% if user.profile.user_types.all %}
    {% for user_type in user.profile.user_types.all %}
        {% if user_type.name == "ad" %}
            <li>
                <a href="{% url admin:index %}" class="round button dark ic-settings image-left">Admin</a>
            </li>
        {% endif %}
    {% endfor %}
{% endif %}

user.profile is simply going from Django's User to my UserProfile.

But this seems a little verbose and clunky. Is there a simpler way? Maybe I should be writing my own custom context processor and pass a variable like is_admin or something, but I never wrote a custom context processor before...

hobbes3
  • 28,078
  • 24
  • 87
  • 116
  • 1
    Perhaps a dumb question, but why not just rely on `User.is_superuser`? Or if by "administrator" you mean any user that would have access to the Django admin `User.is_staff`. Seems like you're just adding extra complexity for no good reason. – Chris Pratt May 07 '12 at 19:10

1 Answers1

6

You can add method is_admin to your UserProfile model moving business logic to models.

Note that construction like

{% if user.profile.user_types.all %}
    {% for user_type in user.profile.user_types.all %}
    ...
    {% endfor %}
{% endif %}

hits 2 sql query to your db. But with template tag reduces them to 1 hit.

{% with types=user.profile.user_types.all %}
{% if types %}
    {% for user_type in types %}
    ...
    {% endfor %}
{% endif %}
{% endwith %}

Actually the best place for this is in models. But you should learn what django offers for your purpose (contrib.auth, permissions, user groups). Probably you reinvent the wheel.

Then condition {% if user_type.name == "ad" %} shouldn't be hard coded in your python code (especially in templates).

San4ez
  • 8,091
  • 4
  • 41
  • 62