DRF Framework - разрешить пользователю CRUD на поле, связанное с другим пользователем, если они находятся в отношениях через другую модель
У меня есть модель Application, которая имеет поля applicant = ForeignKey('User'...) и coapplicant = ForeignKey('User'...).
Существует также модель Income, которая имеет поле user = ForeignKey('User'....
Я хочу разрешить пользователю A создавать, редактировать, удалять Income объекты пользователя B, если A и B находятся в отношениях через Application.
Это значит:
Пользователь A может CRUD доходы пользователя B и наоборот, если существует такой объект Application, где A является заявителем и B созаявителем или A является созаявителем и B заявителем.
Знаете ли вы, как это сделать?
Вы можете написать пользовательское разрешение примерно так:
from django.db.models import F
class IsOwnerOrCoapplicant(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
if obj.user == request.user:
return True
# If application with both users exists return true,
# exclude cases when applicant and coapplicant are the same just in case
if Application.objects.filter(applicant__in=[obj.user, request.user], coapplicant__in=[obj.user, request.user]).exclude(applicant=F('coapplicant')).exists()
return True
return False
вы можете определить отношения "многие ко многим" между пользователем A и другими пользователями, такими как B (которых я буду называть coapplicants с этого момента), используя модель Application. и Django через поля
например:
from Django import models
class User(models.Model):
...
....
coapplicants = models.ManyToManyField(
'User',
through='Application',
through_fields=('applicant', 'coapplicant'),
)
class Application(models.Model):
applicant= models.ForeignKey('User',...)
coapplicant = models.ForeignKey('User'...)
если вы хотите, чтобы оба A и B были в этом отношении, иначе просто используйте одно из applicant или coapplicant в through_fields. смотрите документацию здесь
теперь, когда вы определили отношения между ними, вы можете использовать разрешения на объекты отдыха в Django, чтобы дать пользователю B доступ к редактированию Income объектов, принадлежащих пользователю A. документация здесь
from rest_framework import permissions
class IsOwnerOrCoapplicant(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# assuming Income instance has an attribute named `owner`.
return obj.owner == request.user or request.user.coapplicants.filter(id=obj.owner.id).exists()
если вы добавите это разрешение к ViewSet, работающей с Income объектами, obj аргументом, передаваемым has_object_permission функции, будет Income экземпляр.