Как ограничить поле ManyToManyField в ModelViewSet для отсутствия суперпользователей?

У меня есть 2 модели, связанные отношением ManyToManyField.

class Site(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name


class Device(models.Model):

    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(blank=True, null=True)
    users = models.ManyToManyField(User, related_name='devices', blank=True)
    site = models.ForeignKey(Site, on_delete=models.CASCADE, related_name='devices')

    class Meta:
        verbose_name = "Device"
        verbose_name_plural = "Devices"
        ordering = ['name']

    def __str__(self):
        return self.name

Мой набор представлений:

class SiteViewSet(viewsets.ReadOnlyModelViewSet):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = SiteSerializer

    def get_queryset(self):
        if self.request.user.is_superuser:
            return Site.objects.all().prefetch_related("devices")
        else:
            return Site.objects.filter(
                devices__users=self.request.user
            ).prefetch_related("devices").distinct()

Мои сериализаторы:

class SiteDeviceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Device
        fields = ('id', 'name', )


class SiteSerializer(serializers.ModelSerializer):
    devices = SiteDeviceSerializer(many=True, read_only=True)

    class Meta:
        model = Site
        fields = "__all__"

Если я обращаюсь к своему представлению с правами суперпользователя, оно работает хорошо, у меня есть все результаты. Пример:

 "results": [
        {
            "id": 1,
            "devices": [
                {
                    "id": 1,
                    "name": "test 1"
                },
                {
                    "id": 2,
                    "name": "test 2"
                }
            ],
            "name": "Site test 1"
        },
        {
            "id": 2,
            "devices": [
                {
                    "id": 3,
                    "name": "Test 3"
                }
            ],
            "name": "Site test 2"
        }
    ]

Я создал другого пользователя user1, который не является суперпользователем. Я также добавил этого пользователя в users устройства test 1. Когда я получаю доступ к представлению с этим пользователем, я получаю:

"results": [
        {
            "id": 1,
            "devices": [
                {
                    "id": 1,
                    "name": "test 1"
                },
                {
                    "id": 2,
                    "name": "test 2"
                }
            ],
            "name": "Site test 1"
        }
    ]

Видно, что Site test 2 не появляется, что прекрасно. Но я вижу устройство test 2, а я не должен его видеть, я добавил пользователя user1 только к устройству test 1.

Как это сделать?

Вы можете фильтровать devices также с помощью Prefetch объекта [Django-doc]:

from django.db.models import Prefetch


class SiteViewSet(viewsets.ReadOnlyModelViewSet):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = SiteSerializer

    def get_queryset(self):
        if self.request.user.is_superuser:
            return Site.objects.all().prefetch_related('devices')
        else:
            return Site.objects.filter(
                devices__users=self.request.user
            ).prefetch_related(
                Prefetch('devices', Device.objects.filter(users=self.request.user))
            ).distinct()
Вернуться на верх