Reputation: 281
I'm trying to show user group permissions in Django and show them in a "Drupal" style like a matrix. It works, but it takes too long to make the query and paint it in the template. Is there some way to improve my code? view img up(accomplished),down(views and template.html)
views :
def GroupPermissionsView(request):
title = "Groups Permissions"
groups = Group.objects.all()
permissions = Permission.objects.all()
context = Context({
'title': title,
'groups': groups,
'permissions': permissions,
})
return render(
request,
'forms_permissions.html',
context
)
template:
<table class="table table-striped table-inverse table-responsive table-bordered">
<thead>
<tr>
<th>Permission</th>
{% for group in groups %}
<th>{{ group.name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for permission in permissions %}
<tr>
<td><b>{{permission.name}}<b></td>
{% for group in groups %}
{% if permission in group.permissions.all %}
<td><input type="checkbox" name="" checked="checked"></input></td>
{% else %}
<td><input type="checkbox" ></input></td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
Upvotes: 3
Views: 261
Reputation: 15568
Your problem was that you run more than 4 * 200 queries, one query for every combination or rows and columns (permissions and groups). It is useful to get them all by one query. It is however not easy because the intermediate model of ManyToMany
relationship between Permission
and Group
models is not explicit in django.contrib.auth.models
. You can get that model by Model._meta API
:
>>> GroupPermissions = Permission._meta.get_field('group').through
>>> GroupPermissions
<class 'django.contrib.auth.models.Group_permissions'>
>>> GroupPermissions._meta.db_table # the table that you use in the raw query
'auth_group_permissions'
Put it all together. Prefer a longer view and simple template:
update the view:
from collections import OrderedDict
GroupPermissions = Permission._meta.get_field('group').through
groups = Group.objects.all()
permissions = Permission.objects.all()
permission_group_set = set()
for x in GroupPermissions.objects.all():
permission_group_set.add((x.permission_id, x.group_id))
# row title and cells for every permission
permission_group_table = OrderedDict([
(permission, [(permission.id, group.id) in permission_group_set for group in groups])
for permission in permissions
])
context = Context({
'title': title,
'groups': groups,
'permission_group_table': permission_group_table,
})
update the template
{% for permission, cells in permission_group_table.items %}
<tr><td><b>{{permission.name}}<b></td>
{% for cell in cells %}
{% if cell %}
<td><input type="checkbox" name="" checked="checked"></input></td>
{% else %}
<td><input type="checkbox" ></input></td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
Upvotes: 2