Django保存User模型时Role实例赋值错误的技术求助
问题解决方法
错误原因
你在User模型的save方法中逻辑有误:当从admin提交修改时,self.role被传入的是角色字符串(比如'ADMIN'),但原代码没有正确区分字符串和Role实例的情况,导致查询逻辑出错,无法正确关联Role实例。
修复步骤
1. 给Role模型添加唯一性约束
先给Role的role字段添加唯一约束,避免重复创建相同角色:
class Role(models.Model): # ... 其他代码保持不变 role = models.CharField( max_length=20, choices=ROLE_CHOICES, default=SELLER, unique=True, # 新增:确保每个角色值仅对应一个实例 )
2. 修正User模型的save方法
修改save方法,处理self.role可能是字符串或Role实例的场景:
class User(AbstractUser): # ... 其他代码保持不变 def save(self, *args, **kwargs): # 处理角色赋值:如果传入的是字符串,获取或创建对应的Role实例 if isinstance(self.role, str): role_obj, _ = Role.objects.get_or_create(role=self.role) self.role = role_obj # 调用父类方法完成最终保存 super().save(*args, **kwargs)
3. 配置User Admin类,确保表单字段正确
在users/admin.py中配置User的Admin类,保证角色选择框正确关联Role实例:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from .models import User, Role class UserAdmin(BaseUserAdmin): # 自定义用户修改页面的字段分组 fieldsets = ( (None, {'fields': ('username', 'password')}), ('个人信息', {'fields': ('name', 'role')}), ('权限', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}), ('重要日期', {'fields': ('last_login', 'date_joined')}), ) # 自定义用户添加页面的字段 add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2', 'name', 'role'), }), ) # 确保角色字段的选项是所有Role实例 def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) form.base_fields['role'].queryset = Role.objects.all() return form admin.site.register(User, UserAdmin)
4. 移除无用的role_choices属性
User模型中的role_choices属性是多余的,ForeignKey字段在admin中会自动生成基于Role实例的选择框,直接删除即可:
# 删除这段代码 @property def role_choices(self): return [(role.id, role.role) for role in Role.objects.all()]
验证修复
完成修改后,运行以下命令更新数据库:
python3 manage.py makemigrations python3 manage.py migrate
重新进入admin修改用户角色,即可正常保存,不会再出现Cannot assign "'ADMIN'": "User.role" must be a "Role" instance.的错误。
内容的提问来源于stack exchange,提问作者Philippe Haumesser
相关产品推荐
相关产品推荐

