Как определить разрешения на уровне объекта для отношений внешнего ключа - PullRequest
0 голосов
/ 09 февраля 2019

У меня проблемы с определением разрешений на уровне объекта для отношений с внешним ключом в моем ModelViewSet.Я не уверен, если это вполне возможно, что я пытаюсь сделать, или есть лучшее решение, но любой намек в правильном направлении будет высоко ценится.Для краткости я сократил модели и сериализаторы.

У меня есть следующие модели:

class Team(models.Model):
    name = models.CharField(max_length=50)

class CustomUser(AbstractUser):
    teams = models.ManyToManyField(Team)

class Client(models.Model):
    name = models.CharField(max_length=50)
    owner = models.ForeignKey(Team, on_delete=models.CASCADE)

class FinancialAccount(models.Model):
    account_name = models.CharField(max_length=50)
    client = models.ForeignKey(Client, on_delete=models.CASCADE)

Тогда у меня есть следующие сериализаторы:

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = ('name', 'owner')

class FinancialAccountSerializer(serializers.ModelSerializer):
    owner = serializers.SerializerMethodField()

    class Meta:
        model = FinancialAccount
        fields = ('name', 'client', 'owner')

    def get_owner(self, obj):
        return client.owner.name

Затем я пытаюсь определить разрешение, которое я могу использовать во всех моих ModelViewSets.Я бы хотел, чтобы это было несколько динамично, так как у меня гораздо больше моделей, чем те, что указаны выше, связанные с Client или даже ниже FinancialAccount.Разрешение и viewset следующие:

class IsOwnerTeam(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        teams = request.user.teams.values_list('name', flat=True)
        return obj.owner in teams

class FinancialAccountViewSet(viewsets.ModelViewSet):
    serializer_class = FinancialAccountSerializer
    permission_classes = (IsOwnerTeam, )

    def get_queryset(self):
        teams = self.request.user.teams.all()
        clients = Client.objects.filter(owner__in=teams)
        return FinancialAccount.objects.filter(account__in=accounts)

Итак, сейчас я получаю эту ошибку: 'FinancialAccount' object has no attribute 'owner', что имеет смысл, потому что у меня нет поля владельца на объекте FinancialAccount,Но я подумал, что если бы у меня было поле владельца в сериализаторе (и я добавил поле владельца в каждый из сериализаторов), я мог бы получить его таким образом.Любая помощь будет оценена!

1 Ответ

0 голосов
/ 09 февраля 2019

Вы можете сделать что-то вроде этого:

class IsOwnerTeam(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if hasattr(obj, 'client'):
            owner = obj.client.owner
        else:
            owner = obj.owner
        teams = request.user.teams.values_list('name', flat=True)
        return owner in teams
...