Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

275
Vistas
Enforcing permissions through a related model in Django Rest Framework

I'm working on building out permissions for an API built with Django REST Framework. Let's say I have the following models:

from django.db import models

class Study(models.Model):
   pass

class Result(models.Model):
   study = models.ForeignKey(Study)
   value = models.IntegerField(null=False)

I have basic serializers and views for both of these models. I'll be using per-object permissions to grant users access to one or more studies. I want users to only be able to view Results for a Study which they have permissions to. There are two ways I can think of to do this, and neither seem ideal:

  1. Keep per-object permissions on Results in sync with Study. This is just a non-starter since we want Study to always be the source of truth.
  2. Write a custom permissions class which checks permissions on the related Study when a user tries to access a Result. This actually isn't too bad, but I couldn't find examples of others doing it this way and it got me thinking that I may be thinking about this fundamentally wrong.

Are there existing solutions for this out there? Or is a custom permissions class the way to go? If so, do you have examples of others who've implemented this way?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

As you stated, you can make custom permission as per the second way: And include the permission in your view:

I am considering your study model with some parameter course, based on that i am writing the solution you can consider for any element in study model

models.py

from django.db import models

class Study(models.Model):
  course = models.CharField(max_length=50)

class Result(models.Model):
   study = models.ForeignKey(Study)
   value = models.IntegerField(null=False)

In permission.py

 from rest_framework import permissions

    class ResultOrReadOnly(permissions.BasePermission):
    
        def has_object_permission(self, request, view, obj):
            if request.method in permissions.SAFE_METHODS and obj.study.course == request.GET.get('course') :

                # read only requests

                return True
            else:

                # other requests such as post, patch, put 

                return obj.study == request.GET.get('course')

And include ,

class ReviewDetail(viewsets.ViewSet):

     permission_classes =[ResultOrReadOnly]

And in urls.py,

Modify it to accept the URL parameter course

over 4 years ago · Santiago Trujillo Denunciar

0

I would create a new field called enrolled_users in the Study model to indicate which all user has access to the particular Study object.

from django.db import models
from django.conf import settings


class Study(models.Model):
    enrolled_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name="studies"
    )
    # other fields


class Result(models.Model):
    study = models.ForeignKey(Study)
    value = models.IntegerField(null=False)

Then, it will very easy in DRF to filter the queryset in the views

# views.py
from .models import Study, Result
from rest_framework.permissions import IsAuthenticated


class StudyModelViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        return Study.objects.filter(enrolled_users=self.request.user)


class ResultModelViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        return Result.objects.filter(study__enrolled_users=self.request.user)

Notes

  • This will handle the object permission (Detail View) request as well
  • This will not return a status code of HTTP 403, but HTTP 404
  • Here I used the ModelViewSet class, but, you can use any views, but the filter plays the role.
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda