使用DRF APITestCase测试用户资料API时遇错误求助
问题解决:Django REST Framework测试中的两个错误修复
一、修复TypeError: 'BasePermissionMetaclass'对象不可迭代
问题原因
- 视图类的
authentication_classes定义错误:LoginView和RegisterView中使用(JWTAuthentication)(小括号),Python会将其解析为单个对象而非可迭代的列表/元组,DRF尝试迭代权限类时触发类型错误。 - 注册/登录视图无需JWT认证:注册、登录是开放接口,不需要提前进行JWT认证,否则未登录用户无法访问。
代码修改
修改views.py中的LoginView和RegisterView:
from rest_framework_simplejwt.tokens import RefreshToken class LoginView(APIView): # 移除JWT认证装饰器与类内错误定义 def post(self, request, *args, **kwargs): serializer = LoginSerializers(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] # 保留正确的JWT生成逻辑,移除多余的login和Token创建代码 refresh = RefreshToken.for_user(user) access_token = str(refresh.access_token) return Response({ 'message': 'Successful login', 'access_token': access_token, 'refresh_token': str(refresh), }, status=status.HTTP_200_OK) class RegisterView(APIView): # 移除JWT认证相关定义 def post(self, request): serializer = RegisterSerializer(data=request.data, context={'request': request}) if serializer.is_valid(): serializer.save() return Response({ 'message': 'successfully registered', }, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
同时修正HomeownerProfileView的authentication_classes定义:
class HomeownerProfileView(APIView): permission_classes = [DjangoModelPermissionsOrAnonReadOnly] # 改为列表形式,确保可迭代 authentication_classes = [JWTAuthentication] serializer_class = HomeownerProfileSerializer # ... 其他方法
二、修复资料测试返回404状态码
问题原因
- 视图
get方法参数错误:未接收request和路由参数,且尝试从kwargs获取username,但路由定义的参数是user_id。 - 视图返回值错误:直接返回数据库对象,而非DRF的
Response对象,未使用序列化器处理数据。 - 测试URL路径错误:请求URL缺少开头的
/,导致路径解析异常。 - 未关联
HomeownerUser实例:测试仅创建User,但HomeownerProfileSerializer对应HomeownerUser模型,需创建关联实例。
代码修改
1. 修改views.py中的HomeownerProfileView
from rest_framework.response import Response from rest_framework import status from django.shortcuts import get_object_or_404 class HomeownerProfileView(APIView): permission_classes = [DjangoModelPermissionsOrAnonReadOnly] authentication_classes = [JWTAuthentication] serializer_class = HomeownerProfileSerializer # 修正get方法参数,接收request与路由参数 def get(self, request, *args, **kwargs): user_id = self.kwargs['user_id'] user = get_object_or_404(User, id=user_id) # 获取关联的HomeownerUser实例 homeowner_profile = get_object_or_404(HomeownerUser, user=user) serializer = self.serializer_class(homeowner_profile) return Response(serializer.data, status=status.HTTP_200_OK)
2. 修改test_profile.py
from rest_framework.test import APITestCase, APIClient from rest_framework import status from ..models import User, HomeownerUser class HomeownerProfileTest(APITestCase): def setUp(self): self.user = User.objects.create_user(username='test_homeowner', password='password321', email='test@example.com') # 创建关联的HomeownerUser实例 self.homeowner_profile = HomeownerUser.objects.create(user=self.user) def test_profile(self): client = APIClient() client.login(username='test_homeowner', password='password321') # URL添加开头的/,确保路径正确 response = client.get(f'/api/users/{self.user.id}/profile/') self.assertEqual(response.status_code, status.HTTP_200_OK)
3. 确保HomeownerUser模型关联正确
from django.db import models from django.contrib.auth.models import User class HomeownerUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) profile_pic = models.ImageField(upload_to='profiles/', blank=True, null=True) street_address = models.CharField(max_length=255, blank=True) homeowner_city = models.CharField(max_length=100, blank=True) homeowner_state = models.CharField(max_length=2, blank=True) homeowner_zip_code = models.CharField(max_length=10, blank=True)
内容的提问来源于stack exchange,提问作者Corveloper
相关产品推荐
相关产品推荐

