简体   繁体   English

Django - 使用电子邮件登录

[英]Django - Login with Email

I want django to authenticate users via email, not via usernames.我希望 django 通过电子邮件而不是用户名对用户进行身份验证。 One way can be providing email value as username value, but I dont want that.一种方法是提供电子邮件值作为用户名值,但我不希望这样。 Reason being, I've a url /profile/<username>/ , hence I cannot have a url /profile/abcd@gmail.com/ .原因是,我有一个网址/profile/<username>/ ,因此我不能有一个网址/profile/abcd@gmail.com/

Another reason being that all emails are unique, but it happen sometimes that the username is already being taken.另一个原因是所有电子邮件都是唯一的,但有时会发生用户名已经被占用的情况。 Hence I'm auto-creating the username as fullName_ID .因此,我将用户名自动创建为fullName_ID

How can I just change let Django authenticate with email?我怎样才能改变让 Django 使用电子邮件进行身份验证?

This is how I create a user.这就是我创建用户的方式。

username = `abcd28`
user_email = `abcd@gmail.com`
user = User.objects.create_user(username, user_email, user_pass)

This is how I login.这就是我登录的方式。

email = request.POST['email']
password = request.POST['password']
username = User.objects.get(email=email.lower()).username
user = authenticate(username=username, password=password)
login(request, user)

Is there any other of of login apart from getting the username first?除了首先获取用户名之外,还有其他登录方式吗?

You should write a custom authentication backend.您应该编写一个自定义身份验证后端。 Something like this will work:像这样的东西会起作用:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

Then, set that backend as your auth backend in your settings:然后,在您的设置中将该后端设置为您的身份验证后端:

AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']

Updated .更新 Inherit from ModelBackend as it implements methods like get_user() already.ModelBackend继承,因为它已经实现了get_user()之类的方法。

See docs here: https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend在此处查看文档: https ://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend

If you're starting a new project, django highly recommended you to set up a custom user model.如果您正在开始一个新项目,django 强烈建议您设置自定义用户模型。 (see https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project ) (见https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project

and if you did it, add three lines to your user model:如果你这样做了,在你的用户模型中添加三行:

class MyUser(AbstractUser):
    USERNAME_FIELD = 'email'
    email = models.EmailField(_('email address'), unique=True) # changes email to unique and blank to false
    REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS

Then authenticate(email=email, password=password) works, while authenticate(username=username, password=password) stops working.然后authenticate(email=email, password=password)工作,而authenticate(username=username, password=password)停止工作。

Email authentication for Django 3.x Django 3.x 的电子邮件身份验证

For using email/username and password for authentication instead of the default username and password authentication, we need to override two methods of ModelBackend class: authenticate() and get_user():为了使用电子邮件/用户名和密码进行身份验证,而不是默认的用户名和密码身份验证,我们需要重写 ModelBackend 类的两个方法:authenticate() 和 get_user():

The get_user method takes a user_id – which could be a username, database ID or whatever, but has to be unique to your user object – and returns a user object or None. get_user 方法接受一个 user_id——它可以是用户名、数据库 ID 或其他任何东西,但必须对你的用户对象是唯一的——并返回一个用户对象或 None。 If you have not kept email as a unique key, you will have to take care of multiple result returned for the query_set.如果您没有将电子邮件保留为唯一键,则必须处理为 query_set 返回的多个结果。 In the below code, this has been taken care of by returning the first user from the returned list.在下面的代码中,通过从返回的列表中返回第一个用户来解决这个问题。

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try: #to allow authentication through phone number or any other field, modify the below statement
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

By default, AUTHENTICATION_BACKENDS is set to:默认情况下,AUTHENTICATION_BACKENDS 设置为:

['django.contrib.auth.backends.ModelBackend']

In settings.py file, add following at the bottom to override the default:在 settings.py 文件中,在底部添加以下内容以覆盖默认值:

AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)

Django 4.0姜戈 4.0

There are two main ways you can implement email authentication, taking note of the following:有两种主要方法可以实现电子邮件身份验证,请注意以下几点:

  • emails should not be unique on a user model to mitigate misspellings and malicious use.电子邮件在用户模型上应该是唯一的,以减少拼写错误和恶意使用。
  • emails should only be used for authentication if they are verified (as in we have sent a verification email and they have clicked the verify link).只有经过验证的电子邮件才应用于身份验证(如我们已发送验证电子邮件并且他们已单击验证链接)。
  • We should only send emails to verified email addresses.我们应该经过验证的电子邮件地址发送电子邮件。

Custom User Model自定义用户模型

A custom user model is recommended when starting a new project as changing mid project can be tricky.开始新项目时建议使用自定义用户模型,因为更改中间项目可能很棘手。

We will add an email_verified field to restrict email authentication to users with a verified email address.我们将添加一个email_verified字段以将电子邮件身份验证限制为具有经过验证的电子邮件地址的用户。

# app.models.py
from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    email_verified = models.BooleanField(default=False)

We will then create a custom authentication backend that will substitute a given email address for a username.然后,我们将创建一个自定义身份验证后端,它将用给定的电子邮件地址替换用户名。

This backend will work with authentication forms that explicitly set an email field as well as those setting a username field.此后端将与显式设置email字段以及设置username段的身份验证表单一起使用。

# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

UserModel = get_user_model()


class CustomUserModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(
                Q(username__exact=username) | (Q(email__iexact=username) & Q(email_verified=True))
            )
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

We then modify our projects settings.py to use our custom user model and authentication backend.然后我们修改我们的项目settings.py以使用我们的自定义用户模型和身份验证后端。

# project.settings.py

AUTH_USER_MODEL = "app.User"
AUTHENTICATION_BACKENDS = ["app.backends.CustomUserModelBackend"]

Be sure that you run manage.py makemigrations before you migrate and that the first migration contains these settings.确保在migrate之前运行manage.py makemigrations并且第一次迁移包含这些设置。

Extended User Model扩展用户模型

While less performant than a custom User model (requires a secondary query), it may be better to extend the existing User model in an existing project and may be preferred depending on login flow and verification process.虽然性能不如自定义User模型(需要辅助查询),但在现有项目中扩展现有User模型可能更好,并且根据登录流程和验证过程可能更受欢迎。

We create a one-to-one relation from EmailVerification to whichever User model our project is using through the AUTH_USER_MODEL setting.我们通过AUTH_USER_MODEL设置创建从EmailVerification到我们项目使用的任何User模型的一对一关系。

# app.models.py
from django.conf import settings
from django.db import models


class EmailVerification(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_query_name="verification"
    )
    verified = models.BooleanField(default=False)

We can also create a custom admin that includes our extension inline.我们还可以创建一个自定义管理员,其中包含我们的内联扩展。

# app.admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .models import EmailVerification

UserModel = get_user_model()


class VerificationInline(admin.StackedInline):
    model = EmailVerification
    can_delete = False
    verbose_name_plural = 'verification'


class UserAdmin(BaseUserAdmin):
    inlines = (VerificationInline,)


admin.site.unregister(UserModel)
admin.site.register(UserModel, UserAdmin)

We then create a backend similar to the one above that simply checks the related models verified field.然后,我们创建一个类似于上面的后端,它只检查相关模型verified字段。

# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

UserModel = get_user_model()


class ExtendedUserModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(
                Q(username__exact=username) | (Q(email__iexact=username) & Q(verification__verified=True))
            )
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

We then modify our projects settings.py to use our authentication backend.然后我们修改我们的项目settings.py以使用我们的身份验证后端。

# project.settings.py

AUTHENTICATION_BACKENDS = ["app.backends.ExtendedUserModelBackend"]

You can then makemigrations and migrate to add functionality to an existing project.然后,您可以进行makemigrationsmigrate以向现有项目添加功能。

Notes笔记

  • if usernames are case insensitive change Q(username__exact=username) to Q(username__iexact=username) .如果用户名不区分大小写,则将Q(username__exact=username)更改为Q(username__iexact=username)
  • In production prevent a new user registering with an existing verified email address.在生产中防止新用户使用现有的经过验证的电子邮件地址进行注册。

I had a similar requirement where either username/email should work for the username field.In case someone is looking for the authentication backend way of doing this,check out the following working code.You can change the queryset if you desire only the email.我有一个类似的要求,用户名/电子邮件应该适用于用户名字段。如果有人正在寻找这样做的身份验证后端方式,请查看以下工作代码。如果您只需要电子邮件,您可以更改查询集。

from django.contrib.auth import get_user_model  # gets the user_model django  default or your own custom
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q


# Class to permit the athentication using email or username
class CustomBackend(ModelBackend):  # requires to define two functions authenticate and get_user

    def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()

        try:
            # below line gives query set,you can change the queryset as per your requirement
            user = UserModel.objects.filter(
                Q(username__iexact=username) |
                Q(email__iexact=username)
            ).distinct()

        except UserModel.DoesNotExist:
            return None

        if user.exists():
            ''' get the user object from the underlying query set,
            there will only be one object since username and email
            should be unique fields in your models.'''
            user_obj = user.first()
            if user_obj.check_password(password):
                return user_obj
            return None
        else:
            return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

Also add AUTHENTICATION_BACKENDS = ( 'path.to.CustomBackend', ) in settings.py还要在 settings.py 中添加 AUTHENTICATION_BACKENDS = ( 'path.to.CustomBackend', )

Email and Username Authentication for Django 2.X Django 2.X 的电子邮件和用户名身份验证

Having in mind that this is a common question, here's a custom implementation mimicking the Django source code but that authenticates the user with either username or email, case-insensitively, keeping the timing attack protection and not authenticating inactive users .考虑到这是一个常见问题,这里有一个模仿Django 源代码的自定义实现,但它使用用户名或电子邮件对用户进行身份验证,不区分大小写,保持时间攻击保护并且不对非活动用户进行身份验证

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q

class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

Always remember to add it your settings.py the correct Authentication Backend .永远记得在你的 settings.py 中添加正确的Authentication Backend

It seems that the method of doing this has been updated with Django 3.0.看来这样做的方法已经用 Django 3.0 更新了。

A working method for me has been:对我来说,一种工作方法是:

authentication.py # <-- I placed this in an app (did not work in the project folder alongside settings.py authentication.py # <-- 我把它放在一个应用程序中(在项目文件夹中与 settings.py 并没有工作

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User

class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

Then added this to the settings.py file然后将此添加到 settings.py 文件中

AUTHENTICATION_BACKENDS = (
    'appname.authentication.EmailBackend',
)

I have created a helper for that: function authenticate_user(email, password) .我为此创建了一个助手: function authenticate_user(email, password)

from django.contrib.auth.models import User


def authenticate_user(email, password):
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        return None
    else:
        if user.check_password(password):
            return user

    return None

class LoginView(View):
    template_name = 'myapp/login.html'

    def get(self, request):
        return render(request, self.template_name)

    def post(self, request):
        email = request.POST['email']
        password = request.POST['password']
        user = authenticate_user(email, password)
        context = {}

        if user is not None:
            if user.is_active:
                login(request, user)

                return redirect(self.request.GET.get('next', '/'))
            else:
                context['error_message'] = "user is not active"
        else:
            context['error_message'] = "email or password not correct"

        return render(request, self.template_name, context)

You should customize ModelBackend class.您应该自定义 ModelBackend 类。 My simple code:我的简单代码:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

class YourBackend(ModelBackend):

  def authenticate(self, username=None, password=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        if '@' in username:
            UserModel.USERNAME_FIELD = 'email'
        else:
            UserModel.USERNAME_FIELD = 'username'

        user = UserModel._default_manager.get_by_natural_key(username)
    except UserModel.DoesNotExist:
        UserModel().set_password(password)
    else:
        if user.check_password(password) and self.user_can_authenticate(user):
            return user

And in settings.py file, add:settings.py文件中,添加:

AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']

Authentication with Email and Username For Django 2.x使用 Django 2.x 的电子邮件和用户名进行身份验证

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

class EmailorUsernameModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

In settings.py, add following line,在 settings.py 中,添加以下行,

AUTHENTICATION_BACKENDS = ['appname.filename.EmailorUsernameModelBackend']
from django.contrib.auth.models import User

from django.db import Q

class EmailAuthenticate(object):

    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(email=username) | Q(username=username))
        except User.DoesNotExist:
            return None
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()

        if user.check_password(password):
            return user
        return None

    def get_user(self,user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

And then in settings.py :然后在settings.py

AUTHENTICATION_BACKENDS = (
  'articles.backends.EmailAuthenticate',
)

where articles is my django-app, backends.py is the python file inside my app and EmailAuthenticate is the authentication backend class inside my backends.py file其中articles 是我的django-app, backends.py是我的应用程序中的python 文件, EmailAuthenticate是我的backends.py文件中的身份验证后端类

May, 2022 Update: 2022 年 5 月更新:

This instruction shows how to set up authentication with "email" and "password" instead of "username" and "password" and in this instruction, "username" is removed and I tried not to change the default Django settings as much as possible .该指令显示了如何使用“电子邮件”“密码”而不是“用户名”“密码”来设置身份验证,在该指令中, “用户名”被删除,我尽量不更改默认的 Django 设置

First, run the command below to create "account" application :首先,运行以下命令来创建“帐户”应用程序

python manage.py startapp account

Then, set "account" application to "INSTALLED_APPS" and set AUTH_USER_MODEL = 'account.CustomUser' in "settings.py" as shown below:然后,将“account”应用程序设置为“INSTALLED_APPS” ,并在“settings.py”中设置AUTH_USER_MODEL = 'account.CustomUser' ,如下所示:

# "settings.py"

INSTALLED_APPS = [
    # ...
    "account", # Here
]

AUTH_USER_MODEL = 'account.CustomUser' # Here

Then, create "managers.py" just under "account" folder and create "CustomUserManager" class extending "UserManager" class in "managers.py" as shown below.然后,在“account”文件夹下创建 managers.py”,并在“managers.py”中创建“CustomUserManager”类扩展“UserManager”类,如下所示。 *Just copy & paste the code below to "managers.py" and "managers.py" is necessary to make the command "python manage.py createsuperuser" work properly without any error: *只需将下面的代码复制并粘贴“managers.py”“managers.py”是使命令“python manage.py createsuperuser”正常工作而没有任何错误所必需的:

# "account/managers.py"

from django.contrib.auth.models import UserManager
from django.contrib.auth.hashers import make_password

class CustomUserManager(UserManager): # Here
   
    def _create_user(self, email, password, **extra_fields):
        
        if not email:
            raise ValueError("The given email must be set")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.password = make_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError("Superuser must have is_staff=True.")
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")

        return self._create_user(email, password, **extra_fields)

Then, create "CustomUser" class extending "AbstractUser" class and remove "username" by setting it "None" and set "email" with "unique=True" and set "email" to "USERNAME_FIELD" and set "CustomUserManager" class to "objects" in "account/models.py" as shown below.然后,创建扩展“AbstractUser”类“CustomUser”类并通过将其设置为“None”来删除“username”并将“email”设置为“unique=True”并将“email”设置为“USERNAME_FIELD”并将“CustomUserManager”类设置为“ account/models.py”中的“objects” ,如下所示。 *Just copy & paste the code below to "account/models.py" : *只需将以下代码复制并粘贴“account/models.py”

# "account/models.py"

from django.db import models
from django.contrib.auth.models import AbstractUser
from .managers import CustomUserManager

class CustomUser(AbstractUser):
    username = None # Here
    email = models.EmailField('email address', unique=True) # Here
    
    USERNAME_FIELD = 'email' # Here
    REQUIRED_FIELDS = []

    objects = CustomUserManager() # Here

    class Meta:
        verbose_name = "custom user"
        verbose_name_plural = "custom users"

Or, you can also create "CustomUser" class extending "AbstractBaseUser" and "PermissionsMixin" classes as shown below.或者,您也可以创建扩展“AbstractBaseUser”和“PermissionsMixin”类“CustomUser”类,如下所示。 *This code below with "AbstractBaseUser" and "PermissionsMixin" classes is equivalent to the code above with "AbstractUser" class and as you can see, the code above with "AbstractUser" class is much less code: *下面带有“AbstractBaseUser”和“PermissionsMixin”类的代码等同于上面带有“AbstractUser”类的代码,正如您所见,上面带有“AbstractUser”类的代码要少得多:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from .managers import CustomUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField("first name", max_length=150, blank=True)
    last_name = models.CharField("last name", max_length=150, blank=True)
    email = models.EmailField('email address', unique=True)
    is_staff = models.BooleanField(
        "staff status",
        default=False,
        help_text="Designates whether the user can log into this admin site.",
    )
    is_active = models.BooleanField(
        "active",
        default=True,
        help_text=
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
        ,
    )
    date_joined = models.DateTimeField("date joined", default=timezone.now)

    USERNAME_FIELD = 'email'

    objects = CustomUserManager() # Here

Then, create "forms.py" just under "account" folder and create "CustomUserCreationForm" class extending "UserCreationForm" class and "CustomUserChangeForm" class extending "UserChangeForm" class and set "CustomUser" class to "model" in "Meta" inner class in "CustomUserCreationForm" and "CustomUserChangeForm" classes in "account/forms.py" as shown below.然后,在“account”文件夹下创建 forms.py”并创建“CustomUserCreationForm”类扩展“UserCreationForm”类“CustomUserChangeForm”类扩展“UserChangeForm”类,并在“Meta”内部将“ CustomUser ”类设置为“model” “CustomUserCreationForm”中的“account/forms.py”中的“CustomUserChangeForm”类,如下所示。 *Just copy & paste the code below to "forms.py" : *只需将以下代码复制并粘贴“forms.py”

# "account/forms.py"

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):

    class Meta:
        model = CustomUser
        fields = ('email',)

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('email',)

Then, create "CustomUserAdmin" class extending "UserAdmin" class and set "CustomUserCreationForm" and "CustomUserChangeForm" classes to "add_form" and "form" respectively and set "AdminPasswordChangeForm" class to "change_password_form" then set "CustomUser" and "CustomUserAdmin" classes to "admin.site.register()" in "account/admin.py" as shown below.然后,创建扩展“UserAdmin”类的“ CustomUserAdmin ”类,并将“CustomUserCreationForm”和“CustomUserChangeForm”类分别设置为“add_form”“form” ,并将“AdminPasswordChangeForm”类设置为“change_password_form” ,然后设置“CustomUser”和“CustomUserAdmin”类到“ account/admin.py”中的“admin.site.register()” ,如下所示。 *Just copy & paste the code below to "account/admin.py" : *只需将以下代码复制并粘贴“account/admin.py”

from django.contrib import admin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from django.contrib.auth.forms import AdminPasswordChangeForm
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    fieldsets = (
        (None, {"fields": ("password",)}),
        ("Personal info", {"fields": ("first_name", "last_name", "email")}),
        (
            "Permissions",
            {
                "fields": (
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                ),
            },
        ),
        ("Important dates", {"fields": ("last_login", "date_joined")}),
    )
    add_fieldsets = (
        (
            None,
            {
                "classes": ("wide",),
                "fields": ("email", "password1", "password2"),
            },
        ),
    )
    add_form = CustomUserCreationForm # Here
    form = CustomUserChangeForm # Here
    change_password_form = AdminPasswordChangeForm # Here
    list_display = ("email", "first_name", "last_name", "is_staff")
    list_filter = ("is_staff", "is_superuser", "is_active", "groups")
    search_fields = ("first_name", "last_name", "email")
    ordering = ("email",)
    filter_horizontal = (
        "groups",
        "user_permissions",
    )

admin.site.register(CustomUser, CustomUserAdmin) # Here

Then, run the command below to make migrations and migrate:然后,运行以下命令进行迁移和迁移:

python manage.py makemigrations && python manage.py migrate

Then, run the command below to create a superuser:然后,运行下面的命令来创建一个超级用户:

python manage.py createsuperuser

Then, run the command below to run a server:然后,运行以下命令来运行服务器:

python manage.py runserver 0.0.0.0:8000

Then, open the url below:然后,打开下面的网址:

http://localhost:8000/admin/login/

Finally, you can log in with "email" and "password" as shown below:最后,您可以使用“电子邮件”“密码”登录,如下图所示:

在此处输入图像描述

And this is "Add custom user" page as shown below:这是“添加自定义用户”页面,如下所示:

在此处输入图像描述

For Django 2对于 Django 2

username = get_object_or_404(User, email=data["email"]).username
        user = authenticate(
            request, 
            username = username, 
            password = data["password"]
        )
        login(request, user)

Authentication with Email For Django 2.x使用 Django 2.x 的电子邮件进行身份验证

def admin_login(request):
if request.method == "POST":
    email = request.POST.get('email', None)
    password = request.POST.get('password', None)
    try:
        get_user_name = CustomUser.objects.get(email=email)
        user_logged_in =authenticate(username=get_user_name,password=password)
        if user_logged_in is not None:
            login(request, user_logged_in)
            messages.success(request, f"WelcomeBack{user_logged_in.username}")
            return HttpResponseRedirect(reverse('backend'))
        else:
            messages.error(request, 'Invalid Credentials')
            return HttpResponseRedirect(reverse('admin_login'))
    except:
        messages.warning(request, 'Wrong Email')
        return HttpResponseRedirect(reverse('admin_login'))

else:
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse('backend'))
    return render(request, 'login_panel/login.html')

If You created Custom database, from there if you want to validate your email id and password.如果您创建了自定义数据库,则从那里验证您的电子邮件 ID 和密码。

  1. Fetch the Email id and Password with models.objects.value_list('db_columnname').filter(db_emailname=textbox email)使用models.objects.value_list('db_columnname').filter(db_emailname=textbox email)获取电子邮件 ID 和密码

2.assign in list fetched object_query_list 2.assign in list 获取object_query_list

3.Convert List to String 3.将列表转换为字符串

Ex :前任 :

  1. Take the Html Email_id and Password Values in Views.py获取Views.py中的 Html Email_idPassword

    u_email = request.POST.get('uemail')

    u_pass = request.POST.get('upass')

  2. Fetch the Email id and password from the database从数据库中获取电子邮件 ID 和密码

    Email = B_Reg.objects.values_list('B_Email',flat=True).filter(B_Email=u_email)

    Password = B_Reg.objects.values_list('Password',flat=True).filter(B_Email=u_email)

  3. Take the Email id and password values in the list from the Query value setQuery值集中获取列表中的电子邮件 ID 和密码值

    Email_Value = Email[0]

    Password_Value=Password[0]

  4. Convert list to String将列表转换为字符串

    string_email = ''.join(map(str, Email_Value))

    string_password = ''.join(map(str, Password_Value))

Finally your Login Condition最后你的登录条件

if (string_email==u_email and string_password ==u_pass)

The default user model inherits/ Extends an Abstract class.默认用户模型继承/扩展一个抽象类。 The framework should be lenient to a certain amount of changes or alterations.框架应该对一定数量的变化或变更宽容。

A simpler hack is to do the following: This is in a virtual environment更简单的 hack 是执行以下操作:这是在虚拟环境中

  1. Go to your django installation location and find the Lib folder转到您的 django 安装位置并找到Lib文件夹
  2. navigate to django/contrib/auth/导航到 django/contrib/auth/
  3. find and open the models.py file.找到并打开 models.py 文件。 Find the AbstractUser class line 315找到 AbstractUser 类第 315 行

LINE 336 on the email attribute add unique and set it to true email 属性上的第 336 行添加 unique 并将其设置为 true

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

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
  1. Done, makemigrations & migrate完成,进行迁移和迁移

Do this at you own risk,这样做需要您自担风险,

Pretty simple.很简单。 There is no need for any additional classes.不需要任何额外的课程。

When you create and update a user with an email, just set the username field with the email.当您使用电子邮件创建和更新用户时,只需使用电子邮件设置用户名字段。

That way when you authenticate the username field will be the same value of the email.这样,当您验证用户名字段时,电子邮件的值将相同。

The code:编码:

# Create
User.objects.create_user(username=post_data['email'] etc...)

# Update
user.username = post_data['email']
user.save()

# When you authenticate
user = authenticate(username=post_data['email'], password=password)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM