DRF关联模型权限配置问题:如何限制用户仅操作自有设备数据?
嘿,我来帮你搞定这个Data权限的问题!你已经把Device的权限控制做得很到位了,现在只需要给Data补上对应的权限逻辑,分这几步来就行:
1. 新增Data专属的权限类
首先在permissions.py里添加一个针对Data的权限类,用来检查当前用户是否是该Data所属设备的主人:
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 # 新增这个类,专门控制Data的访问权限 class IsDataOwner(permissions.BasePermission): """ Custom permission to only allow owners of the related device to access Data. """ def has_object_permission(self, request, view, obj): # 检查这条数据所属的设备是否属于当前请求的用户 return obj.device.user == request.user
2. 配置DataViewSet的权限与创建验证
接下来修改views.py里的DataViewSet,加上权限控制,同时确保创建Data时用户只能选择自己的设备:
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, IsDataOwner # 别忘了导入新的权限类 # ... 其他代码 ... class DataViewSet(viewsets.ModelViewSet): """ API endpoint that allows device data to be viewed or edited. """ serializer_class = DataSerializer # 配置权限:必须登录,且是数据所属设备的主人 permission_classes = (permissions.IsAuthenticated, IsDataOwner,) 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) # 可选:在创建环节再加一层验证,防止绕过序列化器的异常情况 def perform_create(self, serializer): if serializer.validated_data['device'].user != self.request.user: raise permissions.PermissionDenied("你只能为自己的设备创建数据") serializer.save() # 优化:让前端只能看到自己的设备选项(针对DRF的可浏览API) def get_serializer(self, *args, **kwargs): serializer = super().get_serializer(*args, **kwargs) # 动态设置device字段的可选范围为当前用户的设备 serializer.fields['device'].queryset = Device.objects.filter(user=self.request.user) return serializer
3. 序列化器层面限制设备选择
最后修改serializers.py里的DataSerializer,从数据验证层面阻止用户选择不属于自己的设备:
from django.contrib.auth.models import User, Group from iot_cloud_app.models import Device, Data from rest_framework import serializers # ... 其他代码 ... class DataSerializer(serializers.HyperlinkedModelSerializer): created = serializers.ReadOnlyField() modified = serializers.ReadOnlyField() # 改用PrimaryKeyRelatedField,方便后续动态过滤可选设备 device = serializers.PrimaryKeyRelatedField(queryset=Device.objects.all()) def validate_device(self, value): # 验证选中的设备是否属于当前用户 if value.user != self.context['request'].user: raise serializers.ValidationError("你只能选择自己名下的设备") return value class Meta: model = Data fields = ('id', 'device', 'payload', 'created', 'modified')
逻辑说明
- 权限类:确保用户只能编辑/删除自己设备的Data,一旦尝试操作不属于自己的数据,会直接返回403权限错误。
- get_queryset过滤:保证用户只能看到自己设备的Data列表,不会获取到他人的数据。
- 序列化器验证:从源头拦截用户选择非自有设备的操作,配合视图层的动态queryset设置,前端(包括DRF的可浏览API)只会显示用户自己的设备选项,体验更友好。
内容的提问来源于stack exchange,提问作者Mert Akozcan
相关产品推荐
相关产品推荐

