You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:07:32