Django v3自定义用户模型与管理器测试报错排查
问题分析与解决方案
这个报错的根源其实藏在你继承的PermissionsMixin里——这个混入类会自动给你的User模型添加groups和user_permissions两个多对多字段。虽然你自己没显式定义它们,但它们确实存在于模型中。
为什么直接用UserManager.create_user没问题,但用APIClient发送请求就报错?因为:
- 你自定义的管理器方法只会处理你传入的字段,不会碰
PermissionsMixin带来的多对多字段; - 但当你用Django REST Framework(DRF)的API客户端请求时,如果你的序列化器(比如
ModelSerializer)默认包含了这些多对多字段,DRF会尝试在创建用户时直接赋值这些字段,而多对多字段是不能直接赋值的,必须用.set()方法,这就触发了报错。
解决步骤
修改你的用户序列化器
如果你用的是ModelSerializer,默认会包含模型的所有字段(包括PermissionsMixin带来的groups和user_permissions)。你需要显式排除这些字段,或者只指定需要序列化的字段:from rest_framework import serializers from .models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User # 只列出你需要处理的字段,排除多对多相关字段 fields = ( 'email', 'password', 'type', 'name', 'nickname', 'phone', 'sex', 'company_name', 'dob', 'profile_img', 'sns_id', 'sns_type' ) # 把password设为只写,避免返回给前端 extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): # 调用自定义管理器的create_user方法创建用户 password = validated_data.pop('password') user = User.objects.create_user(password=password, **validated_data) return user验证序列化器的有效性
你可以在测试用例里先单独测试序列化器,确认没有多对多相关的错误:from .serializers import UserSerializer def test_serializer_valid(self): profile_img = self.generate_photo_file() payload = { # 你的测试payload内容... } serializer = UserSerializer(data=payload) self.assertTrue(serializer.is_valid(), serializer.errors)检查视图配置
确保你的CREATE_USER_URL对应的视图使用了上述的自定义序列化器,而不是默认的序列化器。比如用CreateAPIView的话:from rest_framework.generics import CreateAPIView from .serializers import UserSerializer class UserCreateView(CreateAPIView): serializer_class = UserSerializer queryset = User.objects.all()
这样修改后,DRF就不会再尝试处理groups和user_permissions字段,你的测试应该就能正常通过了。
内容的提问来源于stack exchange,提问作者forJ
相关产品推荐
相关产品推荐

