自定义UserProfile模型下Django-CMS出现FieldError:无法解析'username'字段
Django-CMS 自定义用户模型导致 static_alias 字段报错解决
环境信息
- Django 4.2.5
- Django-cms 4.1.2
- Python 3.11
问题现象
在尝试为static_alias字段输入内容时,触发内部服务器错误,错误信息如下:
Internal Server Error: /en/admin/djangocms_alias/alias/1/change/ django.core.exceptions.FieldError: Unsupported lookup 'username' for BigAutoField or join on the field not permitted. django.core.exceptions.FieldError: Cannot resolve keyword 'username' into field. Choices are: created_usergroups, created_users, djangocms_usersettings, email, filer_clipboards, filer_folder_permissions, filer_owned_folders, first_name, globalpagepermission, groups, id, is_admin, is_staff, is_superuser, last_login, last_name, locking_users, logentry, owned_files, pagepermission, pageuser, password, statetracking, student, teacher, user_permissions, version
自定义用户模型代码
Models.py
class UserProfile(PermissionsMixin, AbstractBaseUser): email = models.EmailField(_('Email Address'), unique=True) password = models.CharField(_('Password'), max_length=255) is_admin = models.BooleanField(default=False, verbose_name='Is Admin') is_staff = models.BooleanField(default=False, verbose_name='Is Staff') first_name = models.CharField(default='', max_length=255, verbose_name='First Name') last_name = models.CharField(default='', max_length=255, verbose_name='Last Name') is_superuser = models.BooleanField(default=False, verbose_name='superuser') USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name'] objects = UserProfileManager() class Meta: verbose_name = _('User Profile') def __str__(self): return self.email
Managers.py
class UserProfileManager(BaseUserManager): """ 自定义用户模型管理器,使用邮箱作为唯一身份验证标识,替代用户名 """ def _create_user(self, email, password, **extra_fields): """ 创建并保存给定邮箱和密码的用户 """ if not email: raise ValueError('必须设置邮箱') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user
forms.py
class UserProfileForm(UserCreationForm): email = forms.EmailField(max_length=255, required=True, widget=forms.TextInput(attrs={'type': 'email', 'class': 'form-control', 'name': 'user-email', 'placeholder': '邮箱', 'data-validetta': 'required,email'})) password1 = forms.CharField(max_length=255, required=True, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', 'name': 'user-password1', 'placeholder': '密码', 'data-validetta': 'required,minLength[4],maxLength[20]'})) password2 = forms.CharField(max_length=255, required=True, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', 'name': 'user-password2', 'placeholder': '确认密码', 'data-validetta': 'required,minLength[4],maxLength[20],equalTo[password1]'})) first_name = forms.CharField(max_length=255, required=True, widget=forms.TextInput(attrs={'type': 'text', 'name': 'user-first_name', 'placeholder': '名字', 'data-validetta': 'required'})) last_name = forms.CharField(max_length=255, required=True, widget=forms.TextInput(attrs={'type': 'text', 'name': 'user-last_name', 'placeholder': '姓氏', 'data-validetta': 'required'})) class Meta: model = UserProfile fields = ('email', 'password1', 'password2', 'first_name', 'last_name')
完整错误回溯
Internal Server Error: /en/admin/djangocms_alias/alias/ Traceback (most recent call last): File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 1846, in transform return self.try_transform(wrapped, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 1356, in try_transform raise FieldError( django.core.exceptions.FieldError: Unsupported lookup 'username' for BigAutoField or join on the field not permitted. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\contrib\admin\options.py", line 688, in wrapper return self.admin_site.admin_view(view)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\utils\decorators.py", line 134, in _wrapper_view response = view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\views\decorators\cache.py", line 62, in _wrapper_view_func response = view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\contrib\admin\sites.py", line 242, in inner return view(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\utils\decorators.py", line 46, in _wrapper return bound_method(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\utils\decorators.py", line 134, in _wrapper_view response = view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\contrib\admin\options.py", line 1926, in changelist_view cl = self.get_changelist_instance(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\cms\admin\utils.py", line 411, in get_changelist_instance return super().get_changelist_instance(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\contrib\admin\options.py", line 836, in get_changelist_instance return ChangeList( ^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\contrib\admin\views\main.py", line 77, in __init__ self.root_queryset = model_admin.get_queryset(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\djangocms_versioning\admin.py", line 287, in get_queryset content_created_by=Subquery(versions.values(f"created_by__{conf.USERNAME_FIELD}")[:1]), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\query.py", line 1313, in values clone = self._values(*fields, **expressions) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\query.py", line 1308, in _values clone.query.set_values(fields) File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 2460, in set_values self.add_fields(field_names, True) File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 2170, in add_fields cols.append(join_info.transform_function(target, final_alias)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 1850, in transform raise last_field_exception File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 1823, in setup_joins path, final_field, targets, rest = self.names_to_path( ^^^^^^^^^^^^^^^^^^^ File "C:\Users\warre\ssenv\ssenv\Lib\site-packages\django\db\models\sql\query.py", line 1724, in names_to_path raise FieldError( django.core.exceptions.FieldError: Cannot resolve keyword 'username' into field. Choices are: created_usergroups, created_users, djangocms_usersettings, email, filer_clipboards, filer_folder_permissions, filer_owned_folders, first_name, globalpagepermission, groups, id, is_admin, is_staff, is_superuser, last_login, last_name, locking_users, logentry, owned_files, pagepermission, pageuser, password, statetracking, student, teacher, user_permissions, version
问题原因与解决方法
从回溯信息可知,djangocms_versioning模块代码中尝试用conf.USERNAME_FIELD拼接查询字段,但该配置仍为默认值username,而自定义用户模型并未设置username字段,而是用email作为USERNAME_FIELD,导致查询失败。
解决步骤
- 确保项目
settings.py中正确配置自定义用户模型:
AUTH_USER_MODEL = '你的应用名.UserProfile'
- 若配置后问题仍存在,可通过以下两种方式处理:
- 临时兼容方案:在自定义用户模型中添加
username属性,映射到email字段:
此方法可让依赖class UserProfile(PermissionsMixin, AbstractBaseUser): # 原有字段... @property def username(self): return self.emailusername字段的第三方库正常工作,不影响现有逻辑。 - 修改第三方库逻辑:通过自定义
admin类或信号,覆盖djangocms_versioning中使用username的查询代码,替换为email。
- 临时兼容方案:在自定义用户模型中添加
内容的提问来源于stack exchange,提问作者Lawrence DeSouza
相关产品推荐
相关产品推荐

