博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django+xadmin 打造线上教育平台(二)登录-注册(重制)
阅读量:4687 次
发布时间:2019-06-09

本文共 33160 字,大约阅读时间需要 110 分钟。

Django+xadmin 打造线上教育平台(二)


 一、首页

1)views.py/index函数:

def index(request):    """首页"""    return render(request,"index.html")
View Code

2)html页面:

    
课程机构列表 - 慕学在线网

服务电话:33333333

{
% if request.user.is_authenticated%}
{ { request.user }}

django

{ { request.user }}

{
% else %}
注册
登录 {
% endif %}
{
# header部分#}
{
# 轮播图#}
  • 专业权威

  • 课程最新

  • 名师授课

  • 数据真实

公开课程

名师授课

专业权威

查看更多课程 >

django入门

难度:初级
学习人数:3
慕课网
0

java入门

难度:中级
学习人数:0
北京大学
0

python入门

难度:中级
学习人数:0
南京大学
0

java入门2

难度:高级
学习人数:0
慕课网2
0

java入门3

难度:初级
学习人数:1
慕课网3
0

python入门2

难度:中级
学习人数:0
慕课网666
0
index.html

3)Mxonline/url.py配置:

from django.urls import path,include,re_pathfrom MxOnline import viewsurlpatterns = [    path('index/', views.index, name = 'index'),]
View Code

二、登录

涉及:

  • django自带form表单验证
  • django自带authenticate验证方法

    当用户登录进行authenticate时,会转到我们重新的CustomBackend类进行authenticate验证 ,前提需要将authenticate认证相关配置配置到setting中

1、django自带form表单验证:

 LoginForm:

class LoginForm(forms.Form):    '''登录验证表单'''    username = forms.CharField(required=True)    password = forms.CharField(required=True,min_length=5)

2、重写django自带authenticate验证:

1)在setting.py中配置:

AUTHENTICATION_BACKENDS = ( # 登录认证设置    'MxOnline.views.CustomBackend', #CustomBackend所在路径)

2)在MxOnline/views中创建CustomBackend类:

from django.contrib.auth.backends import ModelBackendfrom users.models import UserProfileclass CustomBackend(ModelBackend):    """    用于mx_login下的authenticate,    setting中需配置全局路径AUTHENTICATION_BACKENDS,当用户登录验证时,用到mx_login下的authenticate进行验证,会    跳到此处进行验证    """    def authenticate(self, request, username=None, password=None, **kwargs):# 重写authenticate方法        try:            # 不希望用户存在两个,get的结果只能有一个,否则报错            user = UserProfile.objects.get(Q(username=username)|Q(email=username))            print(user)            # django的后台中密码是加密处理的,拿到客户登录的密码需要加密后才能对比判断,所以不能直接password==password            # UserProfile继承的AbstractUser中有check_password()方法,会直接将传入的密码加密后于后台的作比较:            print(user.check_password(password))            if user.check_password(password):# 如果为False,则密码不一致,否则密码正确                return user        except Exception as e:            return None
CustomBackend

3)views.py/login:

from django.shortcuts import render,redirect,HttpResponsefrom django.contrib.auth import authenticate ,login ,logoutdef mx_login(request):    """登录"""    login_form = forms.LoginForm()    if request.method == "POST":        login_form = forms.LoginForm(request.POST)        if login_form.is_valid():# form验证通过            # 获取用户提交的用户名和密码            user_name = request.POST.get('username', None)            pass_word = request.POST.get('password', None)            # 成功返回user对象,失败None            user = authenticate(username=user_name, password=pass_word)            # 如果不是null说明验证成功            if user:                if user.is_active:                    # 只有注册激活才能登录                    login(request, user)                # request.session["is_login"] = True                # request.session["username"] = user_name                # request.session.set_expiry(5)                    return redirect("/index/")                else:                    return render(request, 'login.html', {
'msg': '用户未激活', 'login_form': login_form}) # 账号或密码错误 else: return render(request, 'login.html', {
'msg': '用户名或密码错误','login_form': login_form}) else: return render(request, 'login.html', {
'msg': '请正确输入用户名及密码','login_form': login_form}) # return render(request,'login.html',{'login_form': login_form}) return render(request,'login.html')
mx_login

4)url.py配置:

path('login/', views.mx_login, name = 'login'),

5)html页面:

    
慕学在线网登录

成功提交

您的需求提交成功!

邮件验证提示

我们已经向您的邮箱12@13.com发送了邮件,

为保证您的账号安全,请及时验证邮箱

去邮箱验证

没收到,您可以查看您的垃圾邮件和被过滤邮件,

也可以再次发送验证邮件

慕学在线网,在线学习平台!

login.html

 三、退出登录

1、views.py/logout:

def mx_logout(request):    """退出登录"""    logout(request)    return render(request,'index.html')

2、url.py:

path('logout/', views.mx_logout, name = 'logout'),

无HTML页面:


四、注册

客户注册,涉及验证码方面,需要安装captcha相关

步骤:

  1. 客户注册账号,验证账号、密码、验证码
  2. 客户提交注册信息,系统自动给客户回复一封邮件,用于激活账号
  3. 客户收到邮件并打开激活,激活成功可正常登录

1、views.py/register:

from django.shortcuts import render,redirect,HttpResponsefrom MxOnline import formsfrom users.models import UserProfilefrom django.contrib.auth.hashers import make_passwordfrom utils import email_senddef register(request):    """用户注册"""    if request.method == "POST":        register_form = forms.RegisterForm(request.POST)        if register_form.is_valid():            user_name = request.POST.get('email',None)            if UserProfile.objects.filter(email=user_name):                # 用户已经存在,不用再注册                return render(request,'register.html',{
'msg':'用户已经存在','register_form':register_form}) pass_word = request.POST.get('password',None) pass_word = make_password(pass_word) # 密码加密后再保存 UserProfile.objects.create( username=user_name, email=user_name, is_active=False, password=pass_word ) email_send.send_register_email(user_name,'register') # 发送邮件,用户激活账号 return redirect('/login/') else: status_form = True #用于前端注册时判断是否填充客户输入原数据 return render(request,'register.html',locals()) else: register_form = forms.RegisterForm() return render(request,'register.html',{
'register_form':register_form})
register

涉及到django自带的邮件功能:

1)setting.py中配置email相关:

# 邮箱配置EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'EMAIL_HOST = "smtp.163.com"   #以163邮箱为例,SMTP服务器(邮箱需要开通SMTP服务)EMAIL_HOST_PASSWORD = '******'     #SMTP服务授权码DEFAULT_FROM_EMAIL = EMAIL_HOST_USER = "name@163.com"    #我的163邮箱帐号EMAIL_PORT = 25     #163邮箱SMTP服务端口EMAIL_USE_TLS = True     # 163、qq邮箱此值为True,aliyun此值为False,163可以忽略此值EMAIL_SUBJECT_PREFIX = '[yshblog.com]'     #邮件标题前缀,默认是'[django]'
setting.py

2)新建email_send.py:

  • 生成随机验证码
  • 发送邮件相关
import randomfrom users.models import EmailVerifyRecordfrom django.core.mail import send_mailfrom MxOnline import settings# 验证码生成def random_str(random_length=16):    """默认生成16位随机字符串"""    str = ''    # 生成字符串的可选字符串    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'    length = len(chars) - 1    ran_dom = random.Random()    for i in range(random_length):        str += chars[random.randint(0, length)]    return str# 发送邮件def send_register_email(email, send_type="register"):    """    发送邮件    发送前需要先保存到数据库,到时候查询链接是否存在    """    if send_type == 'update_email': # 修改密码操作        code = random_str(4)    else:        code = random_str(16)    # 保存到数据库    EmailVerifyRecord.objects.create(        code=code,        email=email,        send_type=send_type    )    # 定义邮箱内容:    if send_type == "register":        subject = "Mx在线教育注册激活链接"  # 标题        email_body = "请复制打开下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}".format(code)  # 文本邮件体        sender = settings.DEFAULT_FROM_EMAIL  # 发件人        receiver = [email]  # 接收人        email_send_status = send_mail(subject, email_body, sender, receiver)        return email_send_status        # if email_send_status:        #     pass    elif send_type == 'forget':        subject = "Mx在线教育重置密码链接"  # 标题        email_body = "请复制打开下面的链接重置密码:http://127.0.0.1:8000/reset/{0}".format(code)  # 文本邮件体        sender = settings.DEFAULT_FROM_EMAIL  # 发件人        receiver = [email]  # 接收人        email_send_status = send_mail(subject, email_body, sender, receiver)        return email_send_status
View Code

3)url.py配置:

path('register/', views.register, name = 'register'),   # 注册

3.1)发送邮件后客户打开邮件激活账号,需要再user_active(用户账号激活)函数:

def user_active(request,ac_code):    """用户账号激活"""    if request.method == "GET":        ac_record = EmailVerifyRecord.objects.filter(code=ac_code,)        if ac_record:            ac_email = ac_record[0].email            ac_user = UserProfile.objects.get(email=ac_email)            ac_user.is_active = True            ac_user.save()        else:            return render(request,'active_fail.html')        email_count = ac_record[0].email        # return render(request,'login.html',{'email_count':email_count})        return render(request,'active_success.html',{
'email_count':email_count})
user_active

3.2)url.py配置:

re_path(r'^active/(\w+)/',views.user_active,name='user_active'),# 邮箱激活账号

4)HTML页面:

{
% load staticfiles %}
慕学在线注册

账号登录

用户名
密      码
 自动登录
忘记密码
没有账号?立即注册

成功提交

您的需求提交成功!

邮件验证提示

我们已经向您的邮箱12@13.com发送了邮件,

为保证您的账号安全,请及时验证邮箱

去邮箱验证

没收到,您可以查看您的垃圾邮件和被过滤邮件,

也可以再次发送验证邮件

慕学在线,在线学习平台!

register.html

 

至此,注册部分便完成了


 五、忘记密码

步骤:

  1. 客户忘记密码,点击‘忘记密码’操作
  2. 根据客户提交用户信息,系统自动给用户发送邮件用于重置密码
  3. 客户打开邮件中提供的链接,进行密码重置
  4. 服务端更新该用户数据

1、忘记密码:

 1.1)html页面代码:

    
慕学网首页

成功提交

您的需求提交成功!

重新设置密码

请输入新密码

密      码
确 认 密 码
验  证  码

慕学网,在线学习平台!

forget_pwd.html

1.2)views.py/forget_pwd:

def forget_pwd(request):    """忘记密码"""    message ={}    if request.method == "POST":        forgetpwd_form = forms.ForgetPwdForm(request.POST)        if forgetpwd_form.is_valid():            email = request.POST.get('email',None)            user_count = UserProfile.objects.filter(email=email)            if user_count:# 判断邮箱是否存在                send_status = email_send.send_register_email(email,'forget')                # print("send:",send_status)                if send_status:                    return render(request,'send_email_success.html')            else:                message['msg'] = '该邮箱不存在'                message['status'] =True                return render(request,'forgetpwd.html',{
'message':message,'forgetpwd_form':forgetpwd_form}) else: # form表单验证不通过 message['msg'] = '邮箱或验证码错误' message['status'] = True return render(request,'forgetpwd.html',{
'message':message,'forgetpwd_form':forgetpwd_form}) else: forgetpwd_form = forms.ForgetPwdForm() return render(request,'forgetpwd.html',{
'forgetpwd_form':forgetpwd_form})
forget_pwd()

1.3)url.py配置:

path('forgetpwd/',views.forget_pwd,name='forgetpwd'), # 忘记密码

 

2、发送重置密码邮件后,客户点开邮件中提供的链接,需要再处理:

2.1)views.py/pwd_reset:

def pwd_reset(request,ac_code):    """用户重置密码链接"""    if request.method =="GET":        records = EmailVerifyRecord.objects.filter(code=ac_code)        if records:            email = records[0].email            return render(request, "password_reset.html", {
"email": email}) else:# 链接不对 return render(request, "active_fail.html")
pwd_reset()

2,2)url.py配置:

re_path(r'^reset/(\w+)/',views.pwd_reset,name='reset'), # 邮箱重置密码链接 

2.3)无HTML页面,打开重置密码的邮件后,访问邮件内提供的链接,可跳转到重置密码页面:

 

3、密码重置:

3.1)views.py/modify_pwd:

def modify_pwd(request):    """重置密码"""    if request.method == "POST":        modify_form = forms.ModifyPwdForm(request.POST)        if modify_form.is_valid():            pwd1 = request.POST.get("password1", None)            pwd2 = request.POST.get("password2", None)            email = request.POST.get("email", None)            if pwd1 != pwd2:                return render(request, "password_reset.html", {
"email": email, "msg": "密码不一致!"}) user = UserProfile.objects.get(email=email) user.password = make_password(pwd2) user.save() return render(request, "login.html") else: email = request.POST.get("email", None) return render(request, "password_reset.html", {
"email": email, "modify_form": modify_form})
modify_pwd()

 

3.2)url.py:

path('modify_pwd/',views.modify_pwd,name='modify_pwd'), # 重置密码# 这是验证码的url配置    re_path(r'^captcha', include('captcha.urls')),

 

3.3)html页面:

    
密码修改

修改密码

已经通过验证,请设置新密码

{
% csrf_token %}
  • 新 密 码 :
  • 确定密码:
  • {
    % for key,error in modify_form.errors.items %}{
    { key }}:{
    { error }}{% endfor %}{
    { msg }}
password_reset.html

 

至此,用户登录-注册-重置密码方面便完成了


后端完整源码:

views:

from django.shortcuts import render,redirect,HttpResponsefrom django.contrib.auth import authenticate ,login ,logoutfrom django.contrib.auth.backends import ModelBackendfrom MxOnline import formsfrom users.models import UserProfile,EmailVerifyRecordfrom django.db.models import Qfrom django.contrib.auth.hashers import make_passwordfrom utils import email_send# Create your views here.def index(request):    """首页"""    return render(request,"index.html")class CustomBackend(ModelBackend):    """    用于mx_login下的authenticate,    setting中需配置全局路径AUTHENTICATION_BACKENDS,当用户登录验证时,用到mx_login下的authenticate进行验证,会    跳到此处进行验证    """    def authenticate(self, request, username=None, password=None, **kwargs):# 重写authenticate方法        try:            # 不希望用户存在两个,get的结果只能有一个,否则报错            user = UserProfile.objects.get(Q(username=username)|Q(email=username))            print(user)            # django的后台中密码是加密处理的,拿到客户登录的密码需要加密后才能对比判断,所以不能直接password==password            # UserProfile继承的AbstractUser中有check_password()方法,会直接将传入的密码加密后于后台的作比较:            print(user.check_password(password))            if user.check_password(password):# 如果为False,则密码不一致,否则密码正确                return user        except Exception as e:            return Nonedef mx_login(request):    """登录"""    login_form = forms.LoginForm()    if request.method == "POST":        login_form = forms.LoginForm(request.POST)        if login_form.is_valid():# form验证通过            # 获取用户提交的用户名和密码            user_name = request.POST.get('username', None)            pass_word = request.POST.get('password', None)            # 成功返回user对象,失败None            user = authenticate(username=user_name, password=pass_word)            # 如果不是null说明验证成功            if user:                if user.is_active:                    # 只有注册激活才能登录                    login(request, user)                # request.session["is_login"] = True                # request.session["username"] = user_name                # request.session.set_expiry(5)                    return redirect("/index/")                else:                    return render(request, 'login.html', {
'msg': '用户未激活', 'login_form': login_form}) # 账号或密码错误 else: return render(request, 'login.html', {
'msg': '用户名或密码错误','login_form': login_form}) else: return render(request, 'login.html', {
'msg': '请正确输入用户名及密码','login_form': login_form}) # return render(request,'login.html',{'login_form': login_form}) return render(request,'login.html')def mx_logout(request): """退出登录""" logout(request) return render(request,'index.html')def register(request): """用户注册""" if request.method == "POST": register_form = forms.RegisterForm(request.POST) if register_form.is_valid(): user_name = request.POST.get('email',None) if UserProfile.objects.filter(email=user_name): # 用户已经存在,不用再注册 return render(request,'register.html',{
'msg':'用户已经存在','register_form':register_form}) pass_word = request.POST.get('password',None) pass_word = make_password(pass_word) # 密码加密后再保存 UserProfile.objects.create( username=user_name, email=user_name, is_active=False, password=pass_word ) email_send.send_register_email(user_name,'register') # 发送邮件,用户激活账号 return redirect('/login/') else: status_form = True #用于前端注册时判断是否填充客户输入原数据 return render(request,'register.html',locals()) else: register_form = forms.RegisterForm() return render(request,'register.html',{
'register_form':register_form})def user_active(request,ac_code): """用户账号激活""" if request.method == "GET": ac_record = EmailVerifyRecord.objects.filter(code=ac_code,) if ac_record: ac_email = ac_record[0].email ac_user = UserProfile.objects.get(email=ac_email) ac_user.is_active = True ac_user.save() else: return render(request,'active_fail.html') email_count = ac_record[0].email # return render(request,'login.html',{'email_count':email_count}) return render(request,'active_success.html',{
'email_count':email_count})def forget_pwd(request): """忘记密码""" message ={} if request.method == "POST": forgetpwd_form = forms.ForgetPwdForm(request.POST) if forgetpwd_form.is_valid(): email = request.POST.get('email',None) user_count = UserProfile.objects.filter(email=email) if user_count:# 判断邮箱是否存在 send_status = email_send.send_register_email(email,'forget') # print("send:",send_status) if send_status: return render(request,'send_email_success.html') else: message['msg'] = '该邮箱不存在' message['status'] =True return render(request,'forgetpwd.html',{
'message':message,'forgetpwd_form':forgetpwd_form}) else: # form表单验证不通过 message['msg'] = '邮箱或验证码错误' message['status'] = True return render(request,'forgetpwd.html',{
'message':message,'forgetpwd_form':forgetpwd_form}) else: forgetpwd_form = forms.ForgetPwdForm() return render(request,'forgetpwd.html',{
'forgetpwd_form':forgetpwd_form})def pwd_reset(request,ac_code): """用户重置密码链接""" if request.method =="GET": records = EmailVerifyRecord.objects.filter(code=ac_code) if records: email = records[0].email return render(request, "password_reset.html", {
"email": email}) else:# 链接不对 return render(request, "active_fail.html") # return render(request, "login.html")def modify_pwd(request): """重置密码""" if request.method == "POST": modify_form = forms.ModifyPwdForm(request.POST) if modify_form.is_valid(): pwd1 = request.POST.get("password1", None) pwd2 = request.POST.get("password2", None) email = request.POST.get("email", None) if pwd1 != pwd2: return render(request, "password_reset.html", {
"email": email, "msg": "密码不一致!"}) user = UserProfile.objects.get(email=email) user.password = make_password(pwd2) user.save() return render(request, "login.html") else: email = request.POST.get("email", None) return render(request, "password_reset.html", {
"email": email, "modify_form": modify_form})
View Code

 

url.py:

"""MxOnline URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:    https://docs.djangoproject.com/en/2.0/topics/http/urls/Examples:Function views    1. Add an import:  from my_app import views    2. Add a URL to urlpatterns:  path('', views.home, name='home')Class-based views    1. Add an import:  from other_app.views import Home    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')Including another URLconf    1. Import the include() function: from django.urls import include, path    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))"""# from django.contrib import adminfrom django.urls import path,include,re_pathimport xadminfrom MxOnline import viewsurlpatterns = [    path('xadmin/', xadmin.site.urls),    path('index/', views.index, name = 'index'),    path('login/', views.mx_login, name = 'login'),    path('logout/', views.mx_logout, name = 'logout'),    path('register/', views.register, name = 'register'),    # re_path('active/(?P
.*)/',ActiveUserView.as_view(),name='user_active'), re_path(r'^active/(\w+)/',views.user_active,name='user_active'),# 邮箱激活账号 path('forgetpwd/',views.forget_pwd,name='forgetpwd'), # 忘记密码 re_path(r'^reset/(\w+)/',views.pwd_reset,name='reset'), # 邮箱重置密码链接 path('modify_pwd/',views.modify_pwd,name='modify_pwd'), # 重置密码 # 验证码 re_path(r'^captcha', include('captcha.urls')),]
View Code

 

form.Form自定义表单:

from django import formsfrom captcha.fields import CaptchaFieldclass LoginForm(forms.Form):    '''登录验证表单'''    username = forms.CharField(required=True)    password = forms.CharField(required=True,min_length=5)class RegisterForm(forms.Form):    '''注册验证表单'''    email = forms.EmailField(required=True)    password = forms.CharField(required=True,min_length=5)    # 验证码    captcha = CaptchaField(error_messages={
'invalid':'验证码错误'})class ForgetPwdForm(forms.Form): '''忘记密码''' email = forms.EmailField(required=True) captcha = CaptchaField(error_messages={
'invalid': '验证码错误'})class ModifyPwdForm(forms.Form): '''重置密码''' password1 = forms.CharField(required=True, min_length=5) password2 = forms.CharField(required=True, min_length=5)
View Code

 

email_send.py:

import randomfrom users.models import EmailVerifyRecordfrom django.core.mail import send_mailfrom MxOnline import settingsdef random_str(random_length=16):    """默认生成16位随机字符串"""    str = ''    # 生成字符串的可选字符串    chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'    length = len(chars) - 1    ran_dom = random.Random()    for i in range(random_length):        str += chars[random.randint(0, length)]    return str# 发送邮件def send_register_email(email, send_type="register"):    """    发送邮件    发送前需要先保存到数据库,到时候查询链接是否存在    """    if send_type == 'update_email': # 修改密码操作        code = random_str(4)    else:        code = random_str(16)    # 保存到数据库    EmailVerifyRecord.objects.create(        code=code,        email=email,        send_type=send_type    )    # 定义邮箱内容:    if send_type == "register":        subject = "Mx在线教育注册激活链接"  # 标题        email_body = "请复制打开下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}".format(code)  # 文本邮件体        sender = settings.DEFAULT_FROM_EMAIL  # 发件人        receiver = [email]  # 接收人        email_send_status = send_mail(subject, email_body, sender, receiver)        return email_send_status        # if email_send_status:        #     pass    elif send_type == 'forget':        subject = "Mx在线教育重置密码链接"  # 标题        email_body = "请复制打开下面的链接重置密码:http://127.0.0.1:8000/reset/{0}".format(code)  # 文本邮件体        sender = settings.DEFAULT_FROM_EMAIL  # 发件人        receiver = [email]  # 接收人        email_send_status = send_mail(subject, email_body, sender, receiver)        return email_send_status
View Code

 

转载于:https://www.cnblogs.com/Eric15/articles/9568233.html

你可能感兴趣的文章
深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
查看>>
asp.net 页面ajax访问被阻塞
查看>>
word2vec 数学原理
查看>>
Python Day6
查看>>
[Tyvj 模拟赛] 运
查看>>
Pwn-10月25-Hitcon(三)
查看>>
Android欢迎页短暂白屏
查看>>
一个自定义的C#数据库操作基础类 SqlHelper
查看>>
scau 8633 回文划分
查看>>
1057 Stack (分块思想)
查看>>
llvm
查看>>
nginx日志的监控【转】
查看>>
整理一些css在使用中的小技巧(进行中)
查看>>
20150914-构建之法:现代软件工程-阅读笔记
查看>>
抽象类和接口的区别
查看>>
JS生成随机的字母数字组合的字符串
查看>>
Java Class的文件结构
查看>>
[jQuery] form提交到iframe之后,获取iframe里面内容
查看>>
js new到底干了什么,new的意义是什么?
查看>>
MyBatis 基础知识
查看>>