theWanderer4865
theWanderer4865

Reputation: 871

Restrict access to a Class Based View based on the request user and view to be rendered

Here's the scene:

profiles/models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key = True)
    birthdate = models.DateTimeField(blank=True)

    def __unicode__(self):
        return unicode(self.user)


class SpecialProfile(models.Model):
    user = models.OneToOneField(User, primary_key = True)
    ...
# additional fields here

    def __unicode__(self):
        return unicode(self.user)


class SpecialProfileURLs(models.Model):
    profile = models.OneToOneField(SpecialProfile, primary_key = True)
... #some more URLs
homepage_url = models.URLField(blank = True)

    def __unicode__(self):
        return unicode(self.profile)

class SpecialProfileImages(models.Model):
    profile = models.OneToOneField(SpecialProfile, primary_key = True)
    img1 = models.ImageField(blank = True, upload_to='profiles/')
    img2 = models.ImageField(blank = True, upload_to='profiles/')
    img3 = models.ImageField(blank = True, upload_to='profiles/')

    def __unicode__(self):
        return unicode(self.profile)`

profiles/views.py

class PublicProfileView(DetailView):
    template_name = "public_profile.html"
    model = User


class PrivateProfileView(DetailView):
    template_name = 'profile/profile2.html'
    context_object_name = "profile"
    model = User
    pk_field = 'pk'

profiles/urls.py

urlpatterns = patterns("",
    url(r'^$', 'mysite.views.home', name='home'), # give me nothing? just take me home!
    url(r'^(?P<pk>\d+)/$', PrivateProfileView.as_view(), name="profile"),
    url(r'^(?P<username>\w+)/$', ProfileRedirectView.as_view(), name="profile_redirect"),
    url(r"^edit/(?P<profile_id>\w+)/$", EditProfileView.as_view(), name="profile_update_form"),
)

Here's the problem: I want to be able to test whether the user giving the request is the same as the ID used to access a profile. I would intercept at a GET request and check, but django gets mad when I do that (probably because it's a DetailView). Is there a recommended/ non-hackish way to be sure only the user to whom this profile belongs can access it? If not, then the user sending the request should be redirected to the PublicProfileView.

Upvotes: 2

Views: 3182

Answers (2)

theWanderer4865
theWanderer4865

Reputation: 871

It seems bad form to answer my first question but thankfully Alex helped me find exactly what I was looking for:

Per object permissions.

There is a package on GitHub, django-guardian which allows me to set specific permissions to any User or Group for a single model instance.

The documentation is quite thorough.

Upvotes: 1

Alex
Alex

Reputation: 8539

Your solution is a combination of some different things:

1) Use the PermissionsRequiredMixin from django-braces. This is an easy way to add Permission functionality to class-based views. Documentation on the PermissionsRequiredMixin can be found here.

2) Create your own permission. The Django documentation on that is here. Include this permission in your class based view.

Here's a related answer on SO that addresses the same problem in a function-based view. You can use it to help create your permission.

Upvotes: 1

Related Questions