How to make email field unique in model User from contrib.auth in Django

后端 未结 19 1894
夕颜
夕颜 2020-11-27 11:47

I need to patch the standard User model of contrib.auth by ensuring the email field entry is unique:

User._meta.fields[4].unique = True
<         


        
相关标签:
19条回答
  • 2020-11-27 11:54

    Caution: The code below was written for an older version of Django (before Custom User Models were introduced). It contains a race condition, and should only be used with a Transaction Isolation Level of SERIALIZABLE and request-scoped transactions.

    Your code won't work, as the attributes of field instances are read-only. I fear it might be a wee bit more complicated than you're thinking.

    If you'll only ever create User instances with a form, you can define a custom ModelForm that enforces this behavior:

    from django import forms
    from django.contrib.auth.models import User
    
    class UserForm(forms.ModelForm):
        class Meta:
            model = User
    
        def clean_email(self):
            email = self.cleaned_data.get('email')
            username = self.cleaned_data.get('username')
            if email and User.objects.filter(email=email).exclude(username=username).exists():
                raise forms.ValidationError(u'Email addresses must be unique.')
            return email
    

    Then just use this form wherever you need to create a new user.

    BTW, you can use Model._meta.get_field('field_name') to get fields by name, rather than by position. So for example:

    # The following lines are equivalent
    User._meta.fields[4]
    User._meta.get_field('email')
    

    UPDATE

    The Django documentation recommends you use the clean method for all validation that spans multiple form fields, because it's called after all the <FIELD>.clean and <FIELD>_clean methods. This means that you can (mostly) rely on the field's value being present in cleaned_data from within clean.

    Since the form fields are validated in the order they're declared, I think it's okay to occasionally place multi-field validation in a <FIELD>_clean method, so long as the field in question appears after all other fields it depends on. I do this so any validation errors are associated with the field itself, rather than with the form.

    0 讨论(0)
  • 2020-11-27 11:54

    I went to \Lib\site-packages\django\contrib\auth\models and in class AbstractUser(AbstractBaseUser, PermissionsMixin): I changed email to be:

    email = models.EmailField(_('email address'), **unique=True**, blank=True)
    

    With this if you try to register with email address already present in the database you will get message: User with this Email address already exists.

    0 讨论(0)
  • 2020-11-27 11:57

    It's amazing, but I found a best solution for me!

    django-registration have form with checking uniqueness of email field: RegistrationFormUniqueEmail

    example of usage here

    0 讨论(0)
  • 2020-11-27 11:58

    This method won't make email field unique at the database level, but it's worth trying.

    Use a custom validator:

    from django.core.exceptions import ValidationError
    from django.contrib.auth.models import User
    
    def validate_email_unique(value):
        exists = User.objects.filter(email=value)
        if exists:
            raise ValidationError("Email address %s already exists, must be unique" % value)
    

    Then in forms.py:

    from django.contrib.auth.models import User
    from django.forms import ModelForm
    from main.validators import validate_email_unique
    
    class UserForm(ModelForm):
        #....
        email = forms.CharField(required=True, validators=[validate_email_unique])
        #....
    
    0 讨论(0)
  • 2020-11-27 11:58

    Django does not allow direct editing User object but you can add pre_save signal and achieve unique email. for create signals u can follow https://docs.djangoproject.com/en/2.0/ref/signals/. then add the following to your signals.py

     @receiver(pre_save, sender=User)
    def check_email(sender,instance,**kwargs):
        try:
            usr = User.objects.get(email=instance.email)
            if usr.username == instance.username:
                pass
            else:
                raise Exception('EmailExists')
        except User.DoesNotExist:
            pass
    
    0 讨论(0)
  • You can use your own custom user model for this purpose. You can use email as username or phone as username , can have more than one attribute.

    In your settings.py you need to specify below settings AUTH_USER_MODEL = 'myapp.MyUser'.

    Here is the link that can help you . https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#auth-custom-user

    0 讨论(0)
提交回复
热议问题