Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

271
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda