当用户注册时,如何使Django用户电子邮件唯一?
forms.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
我使用django.contrib.auth.models用户。 我是否需要在模型中覆盖用户。当前,该模型未引用用户。
views.py
class SignUp(generic.CreateView):
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
感谢您的想法。
答案 0 :(得分:7)
最好的答案是使用CustomUser
,方法是将AbstractUser
子类化,然后在其中放置唯一的电子邮件地址。例如:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
并使用AUTH_USER_MODEL="app.CustomUser"
更新设置。
但是,如果您不必将唯一的电子邮件存储在数据库中或可能不将其用作用户名字段,则可以更新表单的clean
方法以进行验证。例如:
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
如果您处于项目中期,则可以按照documentation进行更改迁移的方法,简而言之是:
__init__.py
django_migrations
中的所有条目python manage.py makemigrations
python manage.py migrate --fake
db_table
,对自定义模型进行其他更改,生成迁移并应用但是,如果您刚刚开始,请删除迁移目录中__init__.py
以外的数据库和迁移文件。然后创建一个新的数据库,通过python manage.py makemigrations
创建一组新的迁移,并通过python manage.py migrate
应用迁移。
对于其他模型中的引用,可以将其引用到settings.AUTH_USER_MODEL
以避免将来出现任何问题。例如:
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
它将自动引用当前的用户模型。
答案 1 :(得分:1)
您可能对以下内容感兴趣:
可重用的用户模型,具有必需的唯一电子邮件字段和项目中期支持。
它定义了重用原始表(auth_user)的自定义用户模型(如果存在)。如果需要(添加到现有项目中时),它将以正确的顺序重新创建应用的迁移历史记录。
我将不胜感激。
答案 2 :(得分:0)
Django的文档中有一个很好的例子-https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#a-full-example。
您必须在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)
答案 3 :(得分:0)
这是工作代码
在您的任何模型中使用以下代码段。py
models.py
from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True
django版本:3.0.2
答案 4 :(得分:0)
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'
]
答案 5 :(得分:0)
比使用 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']
答案 6 :(得分:0)
如果使用从 AbstractBaseUser
继承的 CustomUser 模型,您可以覆盖 full_clean()
方法来验证您指定的模型字段的唯一约束 unique=True
。这比表单(即 FormClass
)验证更安全。
示例:
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
class CustomUser(AbstractBaseUser):
email = models.EmailField(unique=True)
# ...
def full_clean(self, **kwargs):
"""
Call clean_fields(), clean(), and validate_unique() on the model.
Raise a ValidationError for any errors that occur.
"""
super().full_clean()
注意:在 Django 3.1
上测试答案 7 :(得分:0)
简单的方法: 你可以用信号 示例
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.forms import ValidationError
@receiver(pre_save, sender=User)
def check_email(sender, instance, **kwargs):
email = instance.email
if sender.objects.filter(email=email).exclude(username=instance.username).exists():
raise ValidationError('Email Already Exists')