Как ограничить поле 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()