避免在自定义用户模型中为 django allauth 创建用户名字段
Avoid username field creation in custom user model for django allauth
我正在使用带有 allauth 的自定义用户模型,我需要省略用户名字段。我已经看过文档和一大堆关于使用 ACCOUNT_USER_MODEL_USERNAME_FIELD = None
的 Whosebug 答案,但所有这些仍然导致我的数据库有一个用户名字段。
现在因为数据库仍然有一个 username
字段,在 和 上设置了唯一约束,所以 allauth 不会在上述设置设置为的字段中放置用户名None
,这让我在第一个用户创建后面临 IntegrityError
。我知道我可以通过将上述设置设置为 'username'
来解决这个问题,但我很好奇,我怎么不创建用户名,因为我从不使用它。
我的模型:
class CustomUser(AbstractUser):
# Custom user model for django-allauth
first_name = None
last_name = None
def delete(self):
# Custom delete - make sure user storage is also purged
# Purge the user storage
purge_userstore(self.email)
# Call the original delete method to take care of everything else
super(CustomUser, self).delete()
除了覆盖 delete
函数外,它并没有做太多事情。此覆盖与本主题无关,但为了完整起见,我将其包括在内。它还将 first_name
和 last_name
设置为 None
,这完美地工作并按预期从数据库中删除了这些字段。我试过将 user
设置为 None
但这没有任何作用。我也试过将 username
设置为 None
但这会引发 FieldNotFound
错误 ACCOUNT_USER_MODEL_USERNAME_FIELD = None
我的设置(相关位):
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
)
AUTH_USER_MODEL = 'custom_account.CustomUser'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
我的迁移文件:
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
....
这个移民世代让我百思不得其解。为什么 username
字段仍然存在?为什么它设置为唯一的唯一约束,即使我已经明确设置 ACCOUNT_UNIQUE_EMAIL = True
?
注意:这个迁移文件是从干净的平板生成的,这是第一个也是唯一一个从我提供的代码生成的迁移文件。
起初我以为,我的设置根本没有被读取。但是我检查了 django.conf.settings
和 allauth.account.app_settings
(在 shell 中)是否有这些更改,它们都已更新。这是怎么回事?
注意:在我搜索过的许多Whosebug问题中,特别是this问题似乎完美地解释了我的问题。有一个小问题,allauth 的创建者自己的答案建议使用 ACCOUNT_USER_MODEL_USERNAME_FIELD = "username"
,因为有问题的模型是 "clearly using the username
field"。但是答案并没有解释当您根本不想使用 username
字段时该怎么做。
看起来摆脱 username
字段的唯一方法是覆盖 AbstractUser
的用户名字段 and/or 从头开始使用完全自定义的模型。认为覆盖 AbstractBaseUser
也应该有效,尽管 AbstractBaseUser
提供的功能较少。
class CustomUser(AbstractUser):
# Custom user model for django-allauth
# Remove unnecessary fields
username = None
first_name = None
last_name = None
# Set the email field to unique
email = models.EmailField(_('email address'), unique=True)
# Get rid of all references to the username field
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
此模型将删除 username
字段并使 email
字段唯一,并将对 USERNAME_FIELD
的所有引用更改为 'email'
。请注意 REQUIRED_FIELDS
应该为空,因为 USERNAME_FIELD
不能在其中。使用 allauth 时,这不是问题,电子邮件和密码要求无论如何都由 allauth 管理。
我在问题中提到的设置应该保持不变,特别是-
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
我正在使用带有 allauth 的自定义用户模型,我需要省略用户名字段。我已经看过文档和一大堆关于使用 ACCOUNT_USER_MODEL_USERNAME_FIELD = None
的 Whosebug 答案,但所有这些仍然导致我的数据库有一个用户名字段。
现在因为数据库仍然有一个 username
字段,在 和 上设置了唯一约束,所以 allauth 不会在上述设置设置为的字段中放置用户名None
,这让我在第一个用户创建后面临 IntegrityError
。我知道我可以通过将上述设置设置为 'username'
来解决这个问题,但我很好奇,我怎么不创建用户名,因为我从不使用它。
我的模型:
class CustomUser(AbstractUser):
# Custom user model for django-allauth
first_name = None
last_name = None
def delete(self):
# Custom delete - make sure user storage is also purged
# Purge the user storage
purge_userstore(self.email)
# Call the original delete method to take care of everything else
super(CustomUser, self).delete()
除了覆盖 delete
函数外,它并没有做太多事情。此覆盖与本主题无关,但为了完整起见,我将其包括在内。它还将 first_name
和 last_name
设置为 None
,这完美地工作并按预期从数据库中删除了这些字段。我试过将 user
设置为 None
但这没有任何作用。我也试过将 username
设置为 None
但这会引发 FieldNotFound
错误 ACCOUNT_USER_MODEL_USERNAME_FIELD = None
我的设置(相关位):
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
)
AUTH_USER_MODEL = 'custom_account.CustomUser'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
我的迁移文件:
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
....
这个移民世代让我百思不得其解。为什么 username
字段仍然存在?为什么它设置为唯一的唯一约束,即使我已经明确设置 ACCOUNT_UNIQUE_EMAIL = True
?
注意:这个迁移文件是从干净的平板生成的,这是第一个也是唯一一个从我提供的代码生成的迁移文件。
起初我以为,我的设置根本没有被读取。但是我检查了 django.conf.settings
和 allauth.account.app_settings
(在 shell 中)是否有这些更改,它们都已更新。这是怎么回事?
注意:在我搜索过的许多Whosebug问题中,特别是this问题似乎完美地解释了我的问题。有一个小问题,allauth 的创建者自己的答案建议使用 ACCOUNT_USER_MODEL_USERNAME_FIELD = "username"
,因为有问题的模型是 "clearly using the username
field"。但是答案并没有解释当您根本不想使用 username
字段时该怎么做。
看起来摆脱 username
字段的唯一方法是覆盖 AbstractUser
的用户名字段 and/or 从头开始使用完全自定义的模型。认为覆盖 AbstractBaseUser
也应该有效,尽管 AbstractBaseUser
提供的功能较少。
class CustomUser(AbstractUser):
# Custom user model for django-allauth
# Remove unnecessary fields
username = None
first_name = None
last_name = None
# Set the email field to unique
email = models.EmailField(_('email address'), unique=True)
# Get rid of all references to the username field
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
此模型将删除 username
字段并使 email
字段唯一,并将对 USERNAME_FIELD
的所有引用更改为 'email'
。请注意 REQUIRED_FIELDS
应该为空,因为 USERNAME_FIELD
不能在其中。使用 allauth 时,这不是问题,电子邮件和密码要求无论如何都由 allauth 管理。
我在问题中提到的设置应该保持不变,特别是-
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True