This decorator allows edit or delete for the owner of the record. Snippet applies for every model that has ForeignKey to User. Works for User model too. Works with other decorators as permission_required or similar.
Decorator raise http 403 view if user is not owner.
Usage
@permission_required('blogs.change_entry')
@owner_required(Entry)
def manage_entry(request, object_id=None, object=None):
Decorator populates object kwargs if object_id present, otherwise just returns original view function.
@permission_required('blogs.delete_entry')
@owner_required()
def entry_delete(*args, **kwargs):
kwargs["post_delete_redirect"] = reverse('manage_blogs')
return delete_object(*args, **kwargs)
In generic delete wrapper view returns original view function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | def owner_required(Model=None):
"""
Usage:
@permission_required('blogs.change_entry')
@owner_required(Entry)
def manage_entry(request, object_id=None, object=None):
@permission_required('blogs.delete_entry')
@owner_required()
def entry_delete(*args, **kwargs):
kwargs["post_delete_redirect"] = reverse('manage_blogs')
return delete_object(*args, **kwargs)
"""
def _decorator(viewfunc):
def _closure(request, *args, **kwargs):
user = request.user
grant = False
model = Model
mod_edit = False
if 'object_id' in kwargs:
object_id = int(kwargs['object_id'])
if model:
mod_edit = True
elif 'model' in kwargs:
model = kwargs['model']
object = get_object_or_404(model, pk=object_id)
if user.is_superuser:
grant = True
else:
if user.__class__ == model:
grant = object_id == user.id
else:
names = [rel.get_accessor_name() for rel in user._meta.get_all_related_objects() if rel.model == model]
if names:
grant = object_id in [o.id for o in eval('user.%s.all()' % names[0])]
if not grant:
response = render_to_response("403.html", {'object': object}, context_instance=RequestContext(request))
response.status_code = 403
return response
if mod_edit:
kwargs['object'] = object
response = viewfunc(request, *args, **kwargs)
return response
return wraps(viewfunc)(_closure)
return _decorator
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
Cool idea, but i think the eval statement is not necessary. You could use also getattr instead:
#
Please login first before commenting.