【问题标题】:Making EMail address unique in DJango authentication system使电子邮件地址在 DJango 身份验证系统中唯一
【发布时间】:2017-12-16 01:55:42
【问题描述】:

我需要让DJango认证系统的EMail字段唯一。

我正在使用 Python 3.6.3 和 DJango 1.11.7

为了做到这一点,我发现了这个: Making email field unique with Django User admin

在关注它时,我将下面的代码添加到代表身份验证的应用程序文件夹下的__init__.py。我还尝试将其添加到项目的__init_-.py 文件中。

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

无论哪种方式,我仍然遇到相同的错误(如下所列)。我该如何解决?

TIA

C:\WORK\Software\Python64bitv3.6\python.exe manage.py runserver
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x000001F9D03BCEA0>
Traceback (most recent call last):
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\utils\autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\core\management\commands\runserver.py", line 117, in inner_run
    autoreload.raise_last_exception()
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\utils\autoreload.py", line 251, in raise_last_exception
    six.reraise(*_exception)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\utils\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\utils\autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\apps\registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\apps\config.py", line 94, in create
    module = import_module(entry)
  File "C:\WORK\Software\Python64bitv3.6\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\WORK\AppPython\ContractorsClubBackofficeCode\authorization\__init__.py", line 1, in <module>
    from django.contrib.auth.models import User
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\contrib\auth\models.py", line 4, in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\contrib\auth\base_user.py", line 52, in <module>
    class AbstractBaseUser(models.Model):
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\db\models\base.py", line 110, in __new__
    app_config = apps.get_containing_app_config(module)
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\apps\registry.py", line 247, in get_containing_app_config
    self.check_apps_ready()
  File "C:\WORK\Software\Python64bitv3.6\lib\site-packages\django-1.11.7-py3.6.egg\django\apps\registry.py", line 125, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

更新

您好@solarissmoke,感谢您的意见!

我是 DJango 的新手 - 并且 - 还在学习 :-) 我在其中定义了以下内容。寻找要在数据库级别完成的检查。

forms.py

from django import forms
from django.contrib.auth.models import User
from authorization.models import UserProfileInfo, Mstrgenstate, Mstrgencountry, Mstrgenstoretype, Mstrgensalutationtype, Mstrgenbusinesstype

class UserForm (forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput())

    class Meta():
        model = User
        fields = ('username', 'email', 'password')

    def clean_email(self):
        # Get the email
        email = self.cleaned_data.get('email')

        # Check to see if any users already exist with this email as a username.
        try:
            match = User.objects.get(email=email)
        except User.DoesNotExist:
            # Unable to find a user, this is fine
            return email

        # A user was found with this as a username, raise an error.
        raise forms.ValidationError( "This email address is already in use. Please supply a different email address.")


    def clean_username(self):
        # Get the username
        username = self.cleaned_data.get('username')

        # Check to see if any users already exist with this email as a username.
        try:
            match = User.objects.get(username=username)
        except User.DoesNotExist:
            # Unable to find a user, this is fine
            return username

        # A user was found with this as a username, raise an error.
        raise forms.ValidationError("This userid is already in use. Please supply a different userid.")

class UserProfileInfoForm (forms.ModelForm):
    class Meta():
        model = UserProfileInfo
        fields = ('approle', 'profilepic')

在这里,我使用的模型称为User。在您指定的示例中,您将其命名为MyUser。我也要进行以下更改:

来自:

class Meta():
    model = User
    fields = ('username', 'email', 'password')

到:

class Meta():
    model = MyUser
    fields = ('username', 'email', 'password')

对吗?

TIA

【问题讨论】:

    标签: django email authorization


    【解决方案1】:

    您链接到的解决方案已有 7 年历史,绝对不再是这样做的方法。

    做这种事情的更好方法是使用custom user model。在您的情况下,您将覆盖 email 字段以使其唯一:

    class MyUser(AbstractBaseUser):
        email = models.EmailField(unique=True)
    

    如果电子邮件将成为用户的唯一标识符(即,这是他们用来登录的),那么您还需要设置:

    USERNAME_FIELD = 'email'
    

    关于你的用户类。

    最后告诉 Django 在你的设置文件中使用这个新的用户模型:

    AUTH_USER_MODEL = 'myapp.MyUser'
    

    【讨论】:

    • 感谢您的回复。请参阅更新部分。我只需要确保电子邮件的行为就像它是独一无二的。它不会将登录名替换为整个表的 ID。
    • 在这种情况下不要更改USERNAME_FIELD。您仍然需要将模型中的 email 字段设置为唯一。尝试在 clean 方法中使用该电子邮件检查现有用户对于竞争条件(例如,如果两个用户尝试同时注册)是不安全的。
    • 再次感谢您的回复。很高兴知道:) 我一直在寻找模型级别的解决方案。我使用的数据库是 Oracle。我已经在那里的 EMAIL 字段上添加了一个唯一约束。但是,对我来说 - 这是“最后的手段”。在这种情况下,我使用的是 DJango“用户”模型 [请参阅上面消息中的更新] - 所以 - 我真的没有实际模型(本身)来设置电子邮件以使用。在这种情况下我该怎么办?
    猜你喜欢
    • 2014-05-23
    • 2020-03-12
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多