Django Rest Framework Соответствующие модели Разрешения - PullRequest
0 голосов
/ 01 июня 2018

Я использую DRF для создания простого API.У меня есть 3 связанных модели, пользователь, устройство, данные.(Отношение один-ко-многим между User-Device и Device-Data)

У меня проблема с разрешениями.Прямо сейчас, для отношений Пользователь-Устройство, аутентифицированные пользователи могут только просматривать или редактировать свои собственные Устройства.(И когда они создают устройство, связь устанавливается автоматически.)

Я хочу, чтобы пользователи могли просматривать, создавать или редактировать данные только для своих устройств.Например, пользователь не может создавать Данные или просматривать Данные устройства, которое ему не принадлежит.Я не мог понять, как правильно добиться этого.Вы можете помочь мне с этим?

Вот мои views.py

from django.contrib.auth.models import User, Group
from rest_framework import viewsets, permissions
from iot_cloud_app.serializers import *
from iot_cloud_app.permissions import IsOwner

# Create your views here.

class DeviceViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows devices to be viewed or edited.
    """
    serializer_class = DeviceSerializer
    permission_classes = (
        IsOwner,
    )

    def get_queryset(self):
        """
        Filter devices of the user that made the request.
        """
        return Device.objects.all().filter(user=self.request.user)

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class DataViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows device data to be viewed or edited.
    """
    serializer_class = DataSerializer

    def get_queryset(self):
        """
        Filter data of devices that belongs to user who made the request.
        """
        return Data.objects.all().filter(device__user=self.request.user)

и serializers.py

from django.contrib.auth.models import User, Group
from iot_cloud_app.models import Device, Data
from rest_framework import serializers


class DeviceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Device
        fields = ('id', 'name', 'type', 'code')


class DataSerializer(serializers.HyperlinkedModelSerializer):
    created = serializers.ReadOnlyField()
    modified = serializers.ReadOnlyField()
    class Meta:
        model = Data
        fields = ('id', 'device', 'payload', 'created', 'modified')

изменить: permissions.py

from rest_framework import permissions


class IsOwner(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to do actions.
    """

    def has_object_permission(self, request, view, obj):
        # Permissions are only allowed to the owner of the device.
        return obj.user == request.user

Спасибо.

1 Ответ

0 голосов
/ 01 июня 2018

Поскольку вы переопределяете метод get_queryset класса DataViewSet, пользователи не будут иметь доступа к существующим объектам, они увидят ошибку 404, если устройство объекта не связано с пользователем.Если вам нужна ошибка 403, вместо этого вы можете реализовать пользовательский класс разрешений, аналогичный IsOwner:

class IsDeviceOwner(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # Permissions are only allowed to the owner of the device.
        return obj.device.user == request.user

, и использовать его в viewset:

class DataViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows device data to be viewed or edited.
    """
    serializer_class = DataSerializer
    permission_classes = (IsDeviceOwner,)

    def get_queryset(self):
        """
        Filter data of devices that belongs to user who made the request.
        """
        return Data.objects.all().filter(device__user=self.request.user)

Чтобы ограничить выбор устройства при создании данных, выможет реализовать метод validate_device сериализатора:

class DataSerializer(serializers.HyperlinkedModelSerializer):
    created = serializers.ReadOnlyField()
    modified = serializers.ReadOnlyField()
    class Meta:
        model = Data
        fields = ('id', 'device', 'payload', 'created', 'modified')
    def validate_device(self, value):
        if value.user != self.context['request'].user:
            raise serializers.ValidationError('Wrong device id')
        return value
...