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.