I'm wondering how I might accomplish a simple 'object ownership' system with django models, such that, by default, only the owner of an object may edit it.
I am attempting to allow a 'Management' group to edit all objects on behalf of the object owners, and have at this point added a custom permission:
class Meta:
permissions = (
("manage_object", "Can manage objects"),
)
To establish 'ownership' I've toyed with the idea of adding a def to the model:
def owner(self):
return self.user
But then, how might I go further? I could implement the permissions in a view and display relevant UI with a template, i.e.:
if request.user is object.owner:
# ... do stuff
elseif request.user.has_perm.can_manage: # this line is probably not right
# ... do something else
... and then present different UI elements on a template level.
So, the question is:
Best thanks!
My approach would be adding a method to the model:
class YourModelWithOwnership(models.model):
...
def user_can_manage_me(self, user):
return user == self.user or user.has_perm('your_app.manage_object')
I'd then call that method whenever a permission check is required, and take some action based on the outcome. So for a view that would be
from django.shortcuts import get_object_or_404
...
def view_func(request, item_id):
item = get_object_or_404(YourModelWithOwnership, id=item_id) # or whatever is needed to get the object
if not item.user_can_manage_me(request.user):
# user not allowed to manage
...
else:
...
Later I'd probably realize that that's still quite some boilerplate code to write in every view that needs that test, so I'd implement an exception that's thrown when a user can't manage an object...
class CannotManage(Exception):
pass
...and add another method to the model:
from django.db import models
from django.shortcuts import get_object_or_404
class YourModelWithOwnership(models.model):
...
@classmethod
def get_manageable_object_or_404(cls, user, *args, **kwds):
item = get_object_or_404(cls, *args, **kwds)
if not item.user_can_manage_me(user):
raise CannotManage
return item
Then, in the view functions, this can be used:
def view_func(request, item_id):
item = YourModelWithOwnership.get_manageable_object_or_404(request.user, id=item_id)
...
This will of course raise an exception when the user isn't the owner and does not have the proper permission. That exception can be handled in the process_exception()
method of a custom middleware class so that there's a single handler for all instances where a user is not allowed to mess with the object.
A while back I wrote up the usual technique for doing this in the admin. You may want to read through that to see how the implementation works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With