【问题标题】:Django auth.user with unique email具有唯一电子邮件的 Django auth.user
【发布时间】:2011-08-12 01:14:15
【问题描述】:

我使用 django.auth 系统,我有这个:

class RegisterForm(UserCreationForm):
    username = forms.RegexField(label= "Username" , max_length = 30, regex = r'^[\w]+$', error_messages = {'invalid': "This value may contain only letters, numbers and _ characters."})
    email = forms.EmailField(label = "Email")
    first_name = forms.CharField(label = "First name", required = False)
    last_name = forms.CharField(label = "Last name", required = False)

    class Meta:
        model = User
        fields = ("username", "first_name", "last_name", "email", )

    def save(self, commit = True):
        user = super(RegisterForm, self).save(commit = False)
        user.first_name = self.cleaned_data["first_name"]
        user.last_name = self.cleaned_data["last_name"]
        user.email = self.cleaned_data["email"]
        if commit:
            user.save()
        return user

我想将电子邮件设置为唯一电子邮件并检查此验证的表单。我该怎么做?

【问题讨论】:

标签: python django django-authentication


【解决方案1】:

在你的模型中的某个地方:

from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True

注意unique 之前的下划线。这是实际保存信息的地方。 User._meta.get_field('email').unique 只是一个 @property ,它可以查看它。

这也适用于 syncdb,因此您将与数据库保持一致。

还要注意,从 Django 1.5 开始,您将不必做这些事情,因为用户模型将是可插入的。

【讨论】:

  • 这在 Django 1.8 及更高版本中失败。它说权限被拒绝
  • @Peter:makemigrations 时使用 sudo
  • omg 我找了很久才找到这个。感谢5年前的先生!在工作中被投入到一个 django 项目中,并且想要一个真正的忠实粉丝,因为 django 的好处是它的一些默认类,但如果你不能编辑/附加到它们,那有什么意义呢!但现在我可以了!你是我见过的唯一写这篇文章的人。 @Marek Brzóska 传奇
  • 这会改变用户模型吗??
  • @Irfanwani 添加这个并运行 makemigrations/migrate 创建一个迁移并更新用户模型(在我的例子中,它在 venv venv\lib\site-packages\django\contrib\auth\migrations\0013_auto_20211231_1534.py 中创建了一个迁移,因此更改了用户模型定义)。由于我没有在我部署的 django 应用程序的 git 中包含此迁移,因此它会导致在我的本地 DEV 环境与我部署的 PROD 环境中使用不同的用户模型。在这两个环境中,约束都适用于常规注册页面。唯一的区别是,在创建时在管理面板中的 PROD 中,此约束被忽略。
【解决方案2】:

将此添加到您的表单中。但这不是完美的方式。竞争条件只能通过使用这种形式获得。我建议您在数据库级别添加唯一约束。

def clean_email(self):
    data = self.cleaned_data['email']
    if User.objects.filter(email=data).exists():
        raise forms.ValidationError("This email already used")
    return data

添加唯一约束的SQL:

ALTER TABLE auth_user ADD UNIQUE (email)

【讨论】:

  • 为什么这是一个好方法?另外,如果我使用这种方式并在我的数据库字段中添加一个“unique = True”就可以了吗?
  • 如果没有猴子补丁或修补 django,您将无法更改 django auth.user 模型。所以你不能轻易地将 unique=True 添加到 User 模型中。
【解决方案3】:

我不知道如何使用它,但是

from django.contrib.auth.models import User
User._meta.get_field_by_name('email')[0].unique=True

应该这样做。我猜这在你在 auth 模型上运行 syncdb 之前会出现在你的 models.py 中。打算自己试试这个。

【讨论】:

    【解决方案4】:

    这里描述了覆盖 mumimo 建议的 clean() 方法: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method

    通常您可以在字段定义上使用 unique=True,然后使用 ModelForm,这样它会自动为表单中的所有字段运行 clean(),但如果您使用的是 django.auth 用户类您不能修改字段。

    【讨论】:

    • 我使用 django.auth。我应该用什么代替这个?
    【解决方案5】:

    您可以在抽象用户模型中使用它来做同样的事情:

    class User(AbstractUser):
    ...
    
    class Meta:
        unique_together = ('email',)
    

    【讨论】:

      【解决方案6】:

      在进行注册时,我发现在 django auth 中不需要电子邮件,但在简单验证时,如果我们不提供电子邮件,则会出现 500 错误,因为我们必须在后端检查电子邮件。

      所以要使其成为必需,请添加到 registrationSerializer;

      extra_kwargs = {'email': {'required': True}}
      

      对于独特的电子邮件,其他答案显示了这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 2019-03-09
        • 1970-01-01
        • 1970-01-01
        • 2015-03-02
        • 2021-08-22
        • 1970-01-01
        相关资源
        最近更新 更多