Home > Enterprise >  Get all objects' django guardian permissions of the authenticated user in template
Get all objects' django guardian permissions of the authenticated user in template

Time:08-27

I have an application where I am using django-guardian for object-level permission. In my ListView, I am listing all my instances in a table. In each row, I need to show the edit button if the user has the permission to edit this object.

So, I doing something like:

{% extends  "base.html" %}
{% load guardian_tags %}
{% block content  %}
<table>
    <thead>...</thead>
    <tbody>
        {% for i in items %}
        <tr>
            <td>{{ i.name }}</td>
            <td>
                {% get_obj_perms request.user for i as "i_perms" %}  <!-- this one -->
                {% if "change_item" in i_perms %}
                    <a href="{% url 'edit_item' i.id %}">Edit</a>
                {% endif %}
            </td>
        </tr>
        {% endif %}
    </tbody>
</table>
{% endblock %}

Problem

Doing it that way is not optimized solution from database-wise. This solution makes a database query for each object to get the user permissions. How can I do so but with a single hit to the database to get all the objects' user permissions?

CodePudding user response:

I think you would need to use get_objects_for_user in your view and pass it in to your template via context, eg, in a function based view or as part of your get_extra_context() in a CBV

    from guardian.shortcuts import get_objects_for_user
   
    items = Item.objects.all()
    permitted_items = get_objects_for_user(request.user, 'change_item', klass=items)
    context['permitted_items'] = permitted_items
    ...

then in your template

   {% for i in items %}
    <tr>
        <td>{{ i.name }}</td>
        <td>
            {% if i in permitted_items %}
                <a href="{% url 'edit_item' i.id %}">Edit</a>
            {% endif %}
        </td>
    </tr>
    {% endfor %}
  • Related