Adding per-object permissions to django admin
I would simply add a method to each model is_owned_by(user)
, and it is upto the model to decide if it is owned by that user or not. In most case is_owned_by
can be a generic function in a base model class and you can tweak it in special cases. e.g.
class RentalPhoto(BaseModel):
def is_owned_by(self, user):
return self.rental.is_owned_by(user)
This is generic enough and being explicit you will have full control how things behave.
To add new permission you can add that to your models e.g.
class Rental(models.Model):
# ...
class Meta:
permissions = (
("can_edit_any", "Can edit any rentals"),
)
I think instead of adding two permission for any
and own
, you should add only own
permission , so each object already has can_edit
which you can treat as user can edit only his object, and if user has permission can_edit_any than only he is allowed to edit all
Using this we can extend auth by adding a custom backend e.g.
class PerObjectBackend(ModelBackend):
def has_perm(self, user_obj, perm, obj=None):
allowed = ModelBackend.has_perm(self, user_obj, perm)
if perm.find('any') >=0 :
return allowed
if perm.find('edit') >=0 or perm.find('delete') >=0:
if obj is None:
raise Exception("Perm '%s' needs an object"%perm)
if not obj.is_owned_by(user_obj):
return False
return allowed
This is a very quick implemenation, in reality you can extend permission objects to check if it needs and object or not e.g. permission.is_per_object
instead of doing crude string search but that should also work if you have standard names
If you don't want to implement your own Permission Backend, I recommend you to use https://github.com/chrisglass/django-rulez You will do what you want in a much easier way.