基于Django REST Framework的权限依赖序列化实现问询
Django REST Framework 按角色返回不同用户数据实现方案
可以通过自定义动态序列化器结合权限控制实现这个需求,核心思路是根据访问者的角色以及与被查询用户的关系,动态调整返回的字段集合。以下是具体实现步骤:
1. 定义用户角色(可选,若已有角色体系可跳过)
首先在自定义用户模型中添加角色字段,用于区分普通用户、版主和管理员:
# models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): ROLE_CHOICES = ( ('user', '普通用户'), ('moderator', '版主'), ('admin', '管理员'), ) role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')
2. 自定义权限验证类
实现权限逻辑,确保不同角色的用户能访问对应范围的用户数据:
# permissions.py from rest_framework.permissions import BasePermission class UserDataPermission(BasePermission): def has_object_permission(self, request, view, obj): # 管理员拥有所有用户数据的访问权限 if request.user.role == 'admin': return True # 版主可访问所有用户数据(后续通过序列化器控制字段) if request.user.role == 'moderator': return True # 普通用户仅能访问自身数据 return obj == request.user def has_permission(self, request, view): # 列表视图下,管理员和版主可查看所有用户,普通用户仅能查看自己 if request.user.role in ['admin', 'moderator']: return True return view.action == 'retrieve' and request.user.is_authenticated
3. 实现动态字段序列化器
通过重写get_fields方法,根据当前用户角色和被查询对象的关系,动态添加/移除返回字段:
# serializers.py from rest_framework import serializers from .models import CustomUser class DynamicUserSerializer(serializers.ModelSerializer): def get_fields(self): fields = super().get_fields() request = self.context.get('request') if not request or not request.user.is_authenticated: return {} current_user = request.user target_user = self.instance # 管理员返回全部字段 if current_user.role == 'admin': return fields # 版主移除指定敏感字段(示例为password和phone,可按需调整) if current_user.role == 'moderator': excluded_fields = ['password', 'phone'] for field in excluded_fields: fields.pop(field, None) return fields # 普通用户查询自身:保留ID、用户名、邮箱 if target_user == current_user: allowed_fields = ['id', 'username', 'email'] return {field: fields[field] for field in allowed_fields if field in fields} # 普通用户查询他人:移除邮箱字段 else: fields.pop('email', None) return fields class Meta: model = CustomUser fields = '__all__'
4. 视图层整合
将权限类和序列化器应用到视图中,确保请求上下文传递到序列化器:
# views.py from rest_framework import viewsets from .models import CustomUser from .serializers import DynamicUserSerializer from .permissions import UserDataPermission class UserViewSet(viewsets.ReadOnlyModelViewSet): queryset = CustomUser.objects.all() serializer_class = DynamicUserSerializer permission_classes = [UserDataPermission] def get_serializer_context(self): # 传递request到序列化器上下文,用于角色判断 context = super().get_serializer_context() context['request'] = self.request return context
补充说明
- 如果使用Django内置的
Group而非自定义role字段,只需将权限类和序列化器中的current_user.role == 'admin'替换为current_user.groups.filter(name='管理员').exists()即可。 - 若需要支持写入操作(如更新用户信息),可在序列化器中重写
create/update方法,同样根据角色控制可修改的字段。 - 列表视图中,普通用户默认只能查看自身数据,若需调整可修改
has_permission方法的逻辑。
内容的提问来源于stack exchange,提问作者Doule_
相关产品推荐
相关产品推荐

