Django注册/登陆 机制完全解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jeekmary/article/details/88716770

想必很多人看到登陆完全解析就笑了,你一个注册/登陆还用解析,这么简单的问题还用解析

if name=="admin" and password="123456":
	print("登陆成功")

真的是这样码
先简单介绍下本篇文章涉及到的内容

  1. path和 re_path 配置
  2. FormModel 表单验证
  3. cathcha 验证码
  4. python邮箱发送
  5. 账户激活
  6. django数据库操作
  7. django登陆框架的使用
  8. 错误信息提示
  9. 模板语言应用

  10. 上面是今天文章涉及到的内容,我们今天介绍的注册/登陆绝对并非简单的判断,而是经过一系列的认证的,我们来看几张效果图
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    完成这些操作,基本上就是一个成熟的注册登陆系统,在项目中也就是这么使用,不可能简单的进行判断就可以的,下面就开始一步步来吧

1,定义模型类

User模型类

class UserProfile(AbstractUser):
    nick_name = models.CharField(max_length=50, verbose_name='昵称', default="")
    # null = True 表示这个字段可以不填,在数据库中就会以NULL填充
    # black = True表示得是所对应得表单可以不填,对数据库没有影响
    birthday = models.DateField(verbose_name='生日', null=True, blank=True)
    genders = models.CharField(max_length=10, choices=(("male", "男"), ("female", "女")), default="female")
    address = models.CharField(max_length=100, default="")
    mobile = models.CharField(max_length=11, null=True, blank=True)
    image = models.ImageField(upload_to="image/%Y/%m", default="image/default.png", max_length=100)

    class Meta:
        verbose_name = "用户信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

验证码模型类

class EmailVerifyRecord(models.Model):
    code = models.CharField(max_length=20, verbose_name="验证码")
    email = models.CharField(max_length=50, verbose_name="邮箱")
    send_type = models.CharField(verbose_name="发送类别", choices=(("register", "注册"), ("forget", "忘记密码")), max_length=10)
    send_time = models.DateTimeField(verbose_name="发送时间", default=datetime.now)

    class Meta:
        verbose_name = "邮箱验证码"
        verbose_name_plural = verbose_name

    def __str__(self):
        return '{0}:{1}'.format(self.code, self.email)

继承AbstractUser这个系统自带的用户模型需要再Setting.py文件中添加下面一行代码

AUTH_USER_MODEL = "users.UserProfile"

2,数据库

当然,定义完了模型类肯定要进行迁移,这里就需要进行数据库配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxonline',
        'USER': 'root',
        'HOST': '127.0.0.1',
        'POST': 3306,
    }
}

在此之前,记住要先将app添加到setting.py的install_app中

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
    'courses',
    'operations',
    'organizations',
    'xadmin',
    'crispy_forms',
    'captcha'
]

3,登陆视图函数

# 这里的View是from django.views.generic包下面的View
class LoginView(View):
    # django会根据请求类型来访问下面的方法
    def get(self, request):
        return render(request, 'login.html', {})

    def post(self, request):
        user_name = request.POST.get("username", "admin")
        user_pwd = request.POST.get("password", "admin")
        print("user_name:  ", user_name)
        print("user_pwd:  ", user_pwd)
        form = LoginForm(request.POST)
        if form.is_valid():
            user = auth.authenticate(username=user_name, password=user_pwd)
            if user is not None:
            	# 用户的字段,如果这个字段激活了我们就让用户登陆,否则就报错提示未激活
                if user.is_active:
                    auth.login(request, user)
                    return render(request, 'index.html', {})
                else:
                    return render(request, 'login.html', {"msg": "用户未激活", "login_form": form})
            else:
                return render(request, 'login.html', {"msg": "用户名或者密码错误","login_form": form})
        else:
            return render(request, 'login.html', {"login_form": form})

上面的内容就比较多,我们来一个个介绍
首先我们必须要创建一个Form,读者可以提前往下看,我们将POST传入Form中

  form = LoginForm(request.POST)
        if form.is_valid():

如果不满足要求,form会携带错误信息,我们将Form传到前台界面

<div class="form-group marb20 {% if login_form.errors.username %}errorput{% endif %}">
....
  <div class="error btns login-form-tips" id="jsLoginTips">{% for key,error in login_form.errors.items %}{{ error }}{% endfor %}{{ msg }}</div>

上面第一句表示当用户名出现错误的时候我们会赋予错误的属性,将输入框边框改变,第二句表示将错误信息显示在界面上,读者可以查看前面的截图

当Form检验没有问题的时候就会去数据库中找是否存在这样一个用户,如果存在则调用登陆的方法,这两步使用的方法都是from django.contrib import auth下面的方法

扫描二维码关注公众号,回复: 5614186 查看本文章
 user = auth.authenticate(username=user_name, password=user_pwd)
            if user.is_active:
                    auth.login(request, user)

其实,登陆就是cookie和session的交互效果

4,登陆视图Form

from django import forms
class LoginForm(forms.Form):
    # 这里的username和password必须要和前台的form表单要一直
    username = forms.CharField(required=True)
    password = forms.CharField(required=True, min_length=5)

什么是Form 简单来说Form就是在进行数据库查询之前进行初步的检查输入的时候正确

required=True, min_length=5
# required表示的是不能为空
# min_length表示的是最短的长度

当我们输入的内容不满足要求的时候就会出现上图所示的提示,当然要注意一点是,我们Form里面的字段要和html中的字段一样

5,前台界面

<h2>帐号登录</h2>
                <form action="/login/" method="post" autocomplete="off">
                    <input type='hidden' name='csrfmiddlewaretoken' value='mymQDzHWl2REXIfPMg2mJaLqDfaS1sD5' />
                    <div class="form-group marb20 {% if login_form.errors.username %}errorput{% endif %}">
                        <label>&nbsp;&nbsp;</label>
                        <!--这里的字段要注意保持一致-->
                        <input name="username" id="account_l" type="text" placeholder="手机号/邮箱"  value="{{ login_form.username.value }}"/>
                    </div>
                    <div class="form-group marb8 {% if login_form.errors.password %}errorput{% endif %}">
                        <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
                                   <!--这里的字段要注意保持一致-->
                        <input name="password" id="password_l" type="password" placeholder="请输入您的密码" value="{{ login_form.password.value }}"/>
                    </div>
                    <div class="error btns login-form-tips" id="jsLoginTips">{% for key,error in login_form.errors.items %}{{ error }}{% endfor %}{{ msg }}</div>
                     <div class="auto-box marb38">
                        <label><input type="checkbox" id="jsAutoLogin"> 自动登录</label>
{#                        <a class="fr" href="{% url 'forget_pwd' %}">忘记密码?</a>#}
                        <a class="fr" href="#">忘记密码?</a>
                     </div>
                     <input class="btn btn-green" id="jsLoginBtn" type="submit" value="立即登录 > " />

                {% csrf_token %}
                </form>

6,注册视图函数

class Registeriew(View):
    def     get(self, request):
        register_form = RegisterForm()
        return render(request, "register.html", {"register_form": register_form})

    def post(self, request):
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            user_name = request.POST.get("email", "admin")
            user_pwd = request.POST.get("password", "admin")
            print(user_name)
            print(user_pwd)
            user_profile = UserProfile()
            user_profile.username = user_name
            user_profile.email = user_name
            user_profile.password = make_password(user_pwd)
            user_profile.is_active = False
            user_profile.save()

            send_register_email(user_name, "register")
            return render(request, "login.html")
        return render(request, "register.html", {"register_form": register_form})

同样注册也是需要进行Form判断的,这里我就不多说了

            user_name = request.POST.get("email", "admin")
            user_pwd = request.POST.get("password", "admin")
当初步检查合格后,我们拿到用户名和密码
			user_profile.username = user_name
            user_profile.email = user_name
            user_profile.password = make_password(user_pwd)
            user_profile.is_active = False
            user_profile.save()

这里我们创建一个用户对象,设置好属性的时候调用对象的save()将数据保存到数据库中,这里要注意

  • 设置密码不能直接将明文设置进去,要使用from django.contrib.auth.hashers import make_password这里提供的make_password将密码加密后再进行保存
  • 必须要调用save() 要不然数据没有保存到数据库
    在这里插入图片描述

7,发送邮件

配置邮件

# 邮件发送配置
EMAIL_HOST = "smtp.qq.com"
EMAIL_PORT = 25
EMAIL_HOST_USER = "13***[email protected]"
# 这个需要到邮箱中主动获取,要不然会报错的,这里不是写邮箱密码,而是授权校验吗
EMAIL_HOST_PASSWORD = "lyactzbasaaqjaed"
EMAIL_USER_TLS = False
EMAIL_FORM = "130***[email protected]"

发送邮件的函数

from users.models import EmailVerifyRecord
from random import Random
from django.core.mail import send_mail
from MxOnline.settings import EMAIL_FORM
def random_str(randomlength=8):
    str = ''
    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
    length = len(chars) - 1
    random = Random()
    for i in range(randomlength):
        str += chars[random.randint(0, length)]
    return str


def send_register_email(email, send_type="register"):
    email_record = EmailVerifyRecord()
    code = random_str(16)
    email_record.code = code
    email_record.email = email
    email_record.send_type = send_type
    email_record.save()
    if send_type == "register":
        email_title = "在线网注册激活链接"
        email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)
        send_status = send_mail(email_title,email_body,EMAIL_FORM, [email])
        if send_status:
            print("发送成功")
        else:
            print("发送失败")

配置邮箱激活的url

    re_path('active/(?P<active_code>.*)', ActiveUserView.as_view(), name="active")  # 括号提取active后面的字符串

,很明显我们看到,这里将active_code数据获取了

# 我们再这样一个视图中去接收传过来的active_code,然后到数据库中查找是否存在这样的数据,如果存在将该用户的激活字段改成True就表示该用户已经激活了
class ActiveUserView(View):
    # 用户点击了激活链接
    def get(self, request, active_code):
        print(active_code)
        print("---")
        # 查询记录是否存在
        all_recorder = EmailVerifyRecord.objects.filter(code=active_code)
        if all_recorder:
            for record in all_recorder:
                email = record.email
                user = UserProfile.objects.get(email=email)
                user.is_active = True
                user.save()
                print("激活成功")
        return render(request, "login.html")

上面的视图函数是我们点击了邮箱中的验证码的时候调用的 我们将用户激活字段改变,之后我们就可以调用登陆界面进行登陆了

猜你喜欢

转载自blog.csdn.net/jeekmary/article/details/88716770