Django 用户认证 用户 邮箱登录 邮箱注册 ORM or,and,not form.py FORM ModelForm Paginator 分页 HTMl JQuery 定位元素 ajax django切片 restfulapi 跨域 Ubantu Python Mysql Scrapy 爬虫 导出 Python读写 Pycharm 破解 session re sqlit3 生成式 其他 Prism 富文本 CSS Nginx 部署 请求头 抓包 协议 selenium Ubuntu 宝塔 AI Comfy-ui ollama dify open-webui Git docker
Django实现邮箱登录和注册功能
张建行 2024年12月9日 21:39 50 文章标签: Django 用户认证 用户 邮箱登录 邮箱注册 ORM

一、引言

在Django项目中,默认的认证方式是通过用户名进行登录。但在实际项目中,我们往往需要提供邮箱登录的功能。本文将详细介绍如何实现这一功能,并编写一个用户注册表单,对密码和邮箱进行验证。

二、实现用户名和邮箱登录功能

  1. 创建自定义认证后端

首先,我们需要在views.py文件中创建一个自定义认证后端,重写authenticate方法。以下是代码实现:

from django.contrib.auth import backends
from django.contrib.auth.models import User
from django.db.models import Q

class MyBackend(backends.ModelBackend):
    '''
    主要实现既可以用户名登录也可以使用邮箱登录的功能
    要记得在settings中配置以下字段才会生效
    AUTHENTICATION_BACKENDS = (
    # 这是使用自己写的
    'users.views.MyBackend',
    # 这是django默认使用的认证
    # 'django.contrib.auth.backends.ModelBackend',)
    '''

    # 重写该方法
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # Q 的作用是 可以通过& 和 | 连接起来 当操作符在两个Q对象之间时 会生成一个新的Q对象
            # Q的详细用法可查看该地址 https://www.toutiao.com/article/6809613183938986500/
            # 该表达式的意思是 如果username=username 或者 email=username
            # 实现的具体效果是 无论用户使用用户名登录还是邮箱登录都可以
            user = User.objects.get(Q(username=username) | Q(email=username))
            # 通过check_password() 将用户的明文密码加密成哈希值
            # self.user_can_authenticate(user) 判断用户是否为可用状态,如果被禁用状态,无法通过认证,建议加上
            if user.check_password(password) and self.user_can_authenticate(user):
                return user
        except Exception as e:
            return

 

  1. 在settings.py中配置自定义认证后端

在项目的settings.py文件中,找到AUTHENTICATION_BACKENDS配置项,将其修改为以下内容:

AUTHENTICATION_BACKENDS = (
    'users.views.MyBackend',
)

 

这样,我们就实现了既可以用户名登录也可以使用邮箱登录的功能。

三、编写用户注册表单

接下来,我们编写一个用户注册表单,对密码和邮箱进行验证。以下是forms.py文件中的代码实现:

from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError

class RegisterForm(forms.ModelForm):
    '''
    用户注册时的表单
    '''
    email = forms.EmailField(label='用户邮箱',
                             min_length=3,
                             widget=forms.EmailInput(
                                 attrs={'class': 'form-control',
                                        'placeholder': '请输入邮箱:'}))

    # error_messages={} 自定义错误信息 建议用默认信息就行
    password1 = forms.CharField(label='确认密码',
                                min_length=6,
                                error_messages={'min_length': '密码长度不能少于6位'},
                                widget=forms.PasswordInput(
                                    attrs={'class': 'form-control',
                                           'placeholder': '请输入确认密码:'}
                                ))

    class Meta:
        model = User
        fields = ('username', 'email', 'password')
        widgets = {
            'username': forms.TextInput(
                attrs={'class': 'form-control',
                       'placeholder': '请输入用户名:'}),

            'password': forms.PasswordInput(
                attrs={'class': 'form-control',
                       'placeholder': '请输入密码:'})
        }

    # 重写password1字段的钩子方法
    # 自定义 局部的钩子方法 判断两次密码输入是否一致
    def clean_password1(self):
        # 获取通过验证的密码,判断两次输入的密码是否一致
        password = self.cleaned_data.get('password')
        password1 = self.cleaned_data.get('password1')
        # 如果两次输入的密码不一致,抛出对应的错误
        if password != password1:
            raise ValidationError('两次密码输入不一致,请重新确认!')
        # return 对应的字段
        return password1

    # 定义局部钩子方法,判断email是否已经存在
    def clean_email(self):
        # 获取通过验证的email
        email = self.cleaned_data.get('email')
        exists_email = User.objects.filter(email=email).first()
        if exists_email:
            raise ValidationError('已存在一位使用该邮箱的用户。')
        return email