Python 使用户电子邮件成为唯一的django
当用户注册时,如何使Django用户电子邮件唯一 forms.pyPython 使用户电子邮件成为唯一的django,python,django,Python,Django,当用户注册时,如何使Django用户电子邮件唯一 forms.py class SignUpForm(UserCreationForm): email = forms.EmailField(required=True) class Meta: model = User fields = ("username", "email", "password1", "password2&
class SignUpForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
class SignUp(generic.CreateView):
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
我使用的是from django.contrib.auth.models用户。
我是否需要覆盖模型中的用户。目前该模型未引用用户
视图.py
class SignUpForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
class SignUp(generic.CreateView):
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
Django的文档中有一个很好的例子- 您必须将
AbstractBaseUser
模型中的电子邮件字段声明为unique=True
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
最好的答案是使用
CustomUser
,对AbstractUser
进行子类化,并将唯一的电子邮件地址放在那里。例如:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
from django.core.exceptions import ValidationError
class YourForm(UserCreationForm):
def clean(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email=email).exists():
raise ValidationError("Email exists")
return self.cleaned_data
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
并使用AUTH\u USER\u MODEL=“app.CustomUser”
更新设置
但是,如果您不需要将唯一的电子邮件存储在数据库中,或者可能不将其用作用户名字段,那么您可以更新表单的clean
方法以进行验证。例如:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
from django.core.exceptions import ValidationError
class YourForm(UserCreationForm):
def clean(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email=email).exists():
raise ValidationError("Email exists")
return self.cleaned_data
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
更新
如果您处于项目中期,那么您可以按照关于如何更改迁移的说明进行操作,简言之,即:
\uuuuu init\uuuuuu.py
)django\u迁移
python manage.py makemigrations创建所有迁移文件
python manage.py migrate--false运行伪迁移
\uuuu init\uuuu.py
。然后创建一个新的数据库,通过python manage.py makemigrations
创建一组新的迁移,并通过python manage.py migrate
应用迁移
对于其他模型中的引用,您可以将它们引用到设置.AUTH\u USER\u MODEL
,以避免将来出现任何问题。例如:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
from django.core.exceptions import ValidationError
class YourForm(UserCreationForm):
def clean(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email=email).exists():
raise ValidationError("Email exists")
return self.cleaned_data
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
它将自动引用当前用户模型。您可能会感兴趣: 具有所需唯一电子邮件字段和项目中期支持的可重用用户模型 它定义了对原始表(auth_User)的自定义用户模型重用(如果存在)。如果需要(添加到现有项目中时),它将按正确的顺序重新创建应用迁移的历史记录 我将感谢您的反馈。这是一个工作代码 在任何models.py中使用以下代码段 models.py
from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True
SETTINGS.PY
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend'
]
来自django.contrib.auth.models导入用户
用户。_meta.get_字段('email')。_unique=True
django版本:3.0.2
参考:Django 3.1的工作代码 models.py
from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True
SETTINGS.PY
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend'
]
使用
AbstractBaseUser
#forms.py
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
from django.contrib.auth.form import UserCreationForm
from some_app.validators import validate_email
def validate_email(value):
if User.objects.filter(email = value).exists():
raise ValidationError((f"{value} is taken."),params = {'value':value})
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField(validators = [validate_email])
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
在使用CustomUser模型继承自
AbstractBaseUser
的情况下,您可以覆盖full\u clean()
方法来验证您指定的模型字段上的唯一约束unique=True
。这比表单(即FormClass
)验证更安全
示例:
从django.contrib.auth.models导入AbstractBaseUser
从django.db导入模型
类CustomUser(AbstractBaseUser):
email=models.EmailField(unique=True)
# ...
def完全清洁(自清洁,**kwargs):
"""
在模型上调用clean_fields()、clean()和validate_unique()。
针对发生的任何错误引发ValidationError。
"""
超级().完全清洁()
注意:在上测试,因此当我尝试添加CustomUser时,会出现错误,因为还有其他型号使用django.contrib.auth.User。试图找出我需要做什么来扩展用户模型。我是否需要将所有引用从User更改为CustomUser?@mogoli查看我的评论。您需要删除数据库、迁移等,然后重新开始项目。我知道这是很久以前发布的,但我与上面帖子中的解决方案中的CustomUser有一个问题。我有一个CustomUser带有电子邮件字段,我发现当我想在管理面板中创建新用户时,我遇到了一个完整性错误。错误消息是:“IntegrityError位于/admin/users/customuser/add/。我在启动项目时创建了customuser,但后来添加了电子邮件字段。我想知道这是否是问题所在。重复的键值违反了唯一约束users\u customuser\u email\u 6445acef\u uniq”详细信息:key(email)=()已存在。“@ruddra”您所说的“但如果您不需要在数据库中存储唯一的电子邮件”是什么意思。。。“,检查电子邮件在
用户表单中是否唯一与在用户模型中存储唯一电子邮件不一样吗?e、 g.如果我想使用电子邮件和密码作为登录的主要字段,那么检查电子邮件在UserForm
中是否唯一将是我的工作,或者我应该通过继承AbstractUser
创建CustomUser
模型吗?当我尝试此操作时,不会发生任何事情,我的注册仍然可以接受副本emails@mogoli删除数据库和迁移。在settings.py中,添加AUTH\u USER\u MODEL='new\u USER\u MODEL.MyUser'。然后运行
python manage.py makemigrations new\u user。最后,运行
python manage.py migrate`。到目前为止,将用户模型电子邮件地址约束为唯一的最简单方法——如果表中还没有非唯一值,您甚至可以将其合并到现有项目中。