Django注册/登陆 机制完全解析
想必很多人看到登陆完全解析就笑了,你一个注册/登陆还用解析,这么简单的问题还用解析
if name=="admin" and password="123456":
print("登陆成功")
真的是这样码
先简单介绍下本篇文章涉及到的内容
- path和 re_path 配置
- FormModel 表单验证
- cathcha 验证码
- python邮箱发送
- 账户激活
- django数据库操作
- django登陆框架的使用
- 错误信息提示
- 模板语言应用
- …
上面是今天文章涉及到的内容,我们今天介绍的注册/登陆绝对并非简单的判断,而是经过一系列的认证的,我们来看几张效果图
完成这些操作,基本上就是一个成熟的注册登陆系统,在项目中也就是这么使用,不可能简单的进行判断就可以的,下面就开始一步步来吧
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
下面的方法
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>用 户 名</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>密 码</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***3728@qq.com"
# 这个需要到邮箱中主动获取,要不然会报错的,这里不是写邮箱密码,而是授权校验吗
EMAIL_HOST_PASSWORD = "lyactzbasaaqjaed"
EMAIL_USER_TLS = False
EMAIL_FORM = "130***728@qq.com"
发送邮件的函数
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")
上面的视图函数是我们点击了邮箱中的验证码的时候调用的 我们将用户激活字段改变,之后我们就可以调用登陆界面进行登陆了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)