I recently had the need to use the Django permission system and couple it with newforms admin. There were a couple of tricks in the process so hopefully this will be useful for you.
The scenario, is that I want to have certain users identified as members and then use this permission to control access to other parts of the site. Of course, you can go into the user admin and add the permission bits but it would be better if I could integrate it with the other form that adds additional information to the user.
First, let's setup our model. Here's the stripped down models.py file:
from django.db import models from django.contrib.auth.models import User class Member(models.Model): """ The basic member model. Brings together all the various models into one place. """ user = models.ForeignKey(User, unique=True) date_joined = models.DateField() nick_name = models.CharField(max_length=30) active = models.BooleanField(help_text = "Is this membership active?") # Put any other info here class Meta: permissions = ( ("is_member", "Active Member"), )
The only unique thing about this model is the permissions variable in Meta. All this does is create a new permission called "is_member" whenever you sync the database. It's not terribly useful at this point.
What we'd like to do is make sure that toggling the "active" variable will automatically assign or reassign the permission bit to the corresponding user. We do this in the admin.py file:
from django.contrib.auth.models import User from django.contrib import admin from django.contrib.auth.models import Permission class MemberAdmin(admin.ModelAdmin): """ When we save a member, we need to make sure that the appropriate permissions are added. Then, when we delete, we need to make sure they are removed. """ def save_model(self, request, obj, form, change): """ We use this form to make sure the permissions are up to date and that we store the appropriate info into the user fields too. """ user_id = request.REQUEST.get('user',None) user = User.objects.get(id=user_id) member_status = request.REQUEST.get('active',False) members_only = Permission.objects.get(codename="is_member") if user and member_status: user.user_permissions.add(members_only) elif user: user.user_permissions.remove(members_only) obj.save() def log_deletion(self, request, object, object_repr): members_only = Permission.objects.get(codename="is_member") if object.user: object.user.user_permissions.remove(members_only) super(MemberAdmin, self).log_deletion(request, object, object_repr) admin.site.register(Member,MemberAdmin)
This is where the more interesting parts happen. First, we override save_model and determine the user attached to the member and add the appropriate permission. The key to adding the permission is that we need to get the permission using:
members_only = Permission.objects.get(codename="is_member")
Then, you can add or delete the permission using:
The final piece is making sure that you remove the permission when a user is deleted. We have to override the log_deletion method to know when an object is deleted. Then we just remove the permission.
The really nice thing is that now we can use the permission anywhere we need to and there's no need to write any special permission handling code in your views or templates.