Reputation: 516
I'm working on a Django project and trying to figure out how I can test for user ownership and allow editing or redirect based on the result.
I have a model Scene
. Scene
is linked to User
to track which user created a particular Scene
:
class Scene(models.Model):
user = models.ForeignKey(User)
[rest of Scene model]
I have a URL pattern to edit a particular Scene
object like this:
url(r'^scenes/(?P<pk>[0-9]+)/edit/', SceneUpdateView.as_view(), name='scene-edit'),
I have a logged in user via django-allauth. I want only Scene
owners to be able to edit Scenes
.
I'm trying to figure out how to use a decorator to test if scene.user.id == self.request.user.id
for the particular scene called by the URL.
Do I need to send URL information into permission_required
or user_passes_test
decorators (is this possible)?
How can I make this happen?
Upvotes: 6
Views: 2710
Reputation: 13582
In Function Based Views it's common to see decorators. Yet, in Class Based Views (CBV) it's more common to use Mixins
or QuerySet
.
Adapted from this answer, one can create the following custom Mixin
that overrides the dispatch method
class UserOwnerMixin(object):
def dispatch(self, request, *args, **kwargs):
if self.object.user != self.request.user:
return HttpResponseForbidden()
return super(UserOwnerMixin, self).dispatch(request, *args, **kwargs)
This is a generalized way across multiple model class, as long as one is using user = models.ForeignKey(User)
.
Then use it in the CBV in a similar fashion to
class MyCustomView(UserOwnerMixin, View):
Upvotes: 1
Reputation: 2953
You can use a custom decorator for your specefic need. Note: I'm using function based view, you will have to modify the code to class based view if you want:
import json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.models import User
from yourmodels.models import Scene
#Custom decorator
def must_be_yours(func):
def check_and_call(request, *args, **kwargs):
#user = request.user
#print user.id
pk = kwargs["pk"]
scene = Scene.objects.get(pk=pk)
if not (scene.user.id == request.user.id):
return HttpResponse("It is not yours ! You are not permitted !",
content_type="application/json", status=403)
return func(request, *args, **kwargs)
return check_and_call
#View Function
@must_be_yours
@csrf_protect
def update_scene(request, pk=None):
print pk
if request.method == 'PUT':
#modify merely
pass
Urls:
url(r'^scenes/(?P<pk>[0-9]+)/edit/', 'update_scene'),
Upvotes: 7