如何在Django中配置UserViewSet:允许匿名POST,拒绝未授权GET?
解决Django ViewSet的权限控制问题:允许匿名创建用户但禁止查看
首先先明确你提到的几个疑问:
- ViewSet确实会通过Serializer处理数据:它会把模型实例通过Serializer序列化成响应数据,也会把请求数据通过Serializer反序列化后创建/更新模型。不过你已经通过
extra_kwargs把password设为write_only,这能确保密码不会在GET响应中返回,这个做法是对的。 - 你现在的核心问题是:
ModelViewSet默认对所有动作(list、create、retrieve等)应用统一的permission_classes,所以POST创建用户时也会触发IsAuthenticated校验,导致认证错误。
解决方案:给不同动作设置不同权限
最直接的方式是重写ViewSet的get_permissions方法,根据当前请求的动作(action)返回对应的权限类:
from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.authentication import TokenAuthentication from .models import User from .serializers import UserSerializer class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all().order_by('-date_joined') serializer_class = UserSerializer authentication_classes = (TokenAuthentication,) def get_permissions(self): # 对create动作(即POST请求)开放匿名访问 if self.action == 'create': return [AllowAny()] # 其他动作(list、retrieve、update等)保持认证要求 return [IsAuthenticated()]
这个方法的原理是:DRF会在每个请求到来时调用get_permissions,根据当前的action(DRF会自动识别请求对应的动作,比如POST对应create,GET列表对应list)返回不同的权限列表。这样未登录用户可以正常POST创建账号,但无法访问用户列表或详情。
纠正Serializer的错误
你的UserSerializer里的create方法参数有问题,AllowAny是权限类,不该放在这个方法的参数里,正确的写法应该是:
from rest_framework import serializers from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username', 'email', 'password'] extra_kwargs = {'password': {'write_only': True, 'required': True}} def create(self, validated_data): # 使用create_user方法自动加密密码,这个做法是对的 user = User.objects.create_user(**validated_data) return user
权限控制是在ViewSet层面处理的,Serializer只负责数据的序列化/反序列化和模型实例的创建,不需要在这里传入权限类。
验证效果
修改后:
- 发送POST到
/api/users/:不需要携带Token,能正常创建用户 - 发送GET到
/api/users/或/api/users/{id}/:会返回认证错误,符合预期
内容的提问来源于stack exchange,提问作者Babhoster
相关产品推荐
相关产品推荐

