先实现注册界面的渲染。
创建文件如下:
进入settings.py 进行如下设置:
1.注册app
2.设置templates的文件夹路径
3.设置static文件的路径
STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ]
在myApp中的urls.py文件所起的作用是进行url的拼接。
在views.py文件中返回一个界面的时候,myApp中的urls.py和myPro中的urls.py文件进行路由的传输:
视图文件views.py文件中的代码如下:
from django.shortcuts import render from django.views import View # Create your views here. class RegisterView(View): def get(self,request): return render(request,'register.html')
在myApp文件中添加如下代码:
from django.urls import path from .views import RegisterView urlpatterns = [ path(r'register/',RegisterView.as_view(),name = 'register'), ]
myPro中的urls.py文件中代码如下:
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('login/',include('myApp.urls')), ]
最后来到register.html文件中进行界面的设置,代码如下:
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/css/bootstrap.css"> <title>注册</title> </head> <body> <div class="container"> <h2 class="text-center">请输入注册信息</h2> <form class="form-horizontal" role="form" action="{% url 'register' %}" method="POST"> {% csrf_token %} <div class="form-group"> <label for="inputEmail" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> <input name="email" type="text" class="form-control" id="inputEmail" placeholder="请输入邮箱"> </div> </div> <div class="form-group"> <label for="inputPassword" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input name="password" type="text" class="form-control" id="inputPassword" placeholder="请输入密码"> </div> </div> <div class="form-group" id="right"> <div class="col-sm-10"> {{register_form.captcha}} <label for="" id="show"></label> </div> </div> <div class="form-group"> <h3>{{register_form.errors.email}}</h3> <h3>{{register_form.errors.password}}</h3> <h3>{{register_form.errors.captcha}}</h3> <h3>{{msg}}</h3> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button id="submit" type="submit" class="btn btn-default btn-block btn-success">注册</button> </div> </div> </form> </div> <script src="/static/js/jquery.js"></script> <script src="static/js/bootstrap.js"></script> </body> </html>
此时启动之后,网址url为:http://localhost:8000/login/register/
显示的界面如下:
此时,我们需要做的工作即是:需要在界面上添加一个验证码,并且当填写输入信息的时候,对信息做判断处理。
我们需要在myApp文件中新建一个forms.py文件,里面创建我们的账号密码以及验证码的类。代码如下:
from django import forms from captcha.fields import CaptchaField class RegisterForm(forms.Form): email = forms.EmailField(required=True,error_messages={'invalid':"邮箱格式不正确"}) password = forms.CharField(min_length=6,required=True,error_messages={'min_length':"密码长度不够"}) captcha = CaptchaField(required=True,error_messages={'invalid':"验证码错误"})
然后在views.py文件中进行调用即可,代码如下:
register_form = RegisterForm()
接下来就是处理关于验证码的错误的时候了。
1.
RuntimeError: Model class captcha.models.CaptchaStore doesn't declare anexplicit app_label and isn't in an application in INSTALLED_APPS.
这个错误提示我们需要在settings.py文件中进行注册:
2.在项目里面urls进行设置 Make sure you\'ve included captcha.urls a s explained in the INSTALLATION section on http://readthedocs.org/docs/django-simple-captcha/en/latest/usage.html#installation' 代码如下:
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('login/',include('myApp.urls')), path('captcha/',include('captcha.urls')), ]
3.no such table 重新模型迁移
在模型文件models.py文件中创建字段。代码如下:
from django.db import models from django.contrib.auth.models import AbstractUser # Create your models here. # 模型一旦发生改变,要重新迁移 class UserProfile(AbstractUser): unickname = models.CharField(max_length=20,verbose_name='昵称',null=True,blank=True) ubirthday = models.DateField(auto_now_add=True,verbose_name='生日',null=True) uaddress = models.CharField(max_length=200,verbose_name='地址')
当迁移文件遇到下面错误的时候:
HINT: Add or change a related_name argument to the definition for 'UserProf
ile.user_permissions' or 'User.user_permissions'.
是因为设置文件缺少了一句这样的设置:
AUTH_USER_MODEL = 'myApp.UserProfile'
设置完毕之后,我们需要将验证码生成在界面上,来到register.html文件中,对验证码做接收即可:
<div class="form-group" id="right"> <div class="col-sm-10"> {{register_form.captcha}} <label for="" id="show"></label> </div> </div>
此时刷新界面,可以得到如下的结果:
接下来我们要做的工作就是,当我们刷新验证码的时候,也就是我们鼠标点击验证码的时候,验证码会刷新,当我们鼠标放在验证码上时,鼠标的形状会改变。并且验证码需要一定的时间显示提示用户输入,此时需要在验证码的图片上添加一个点击事件,代码如下:
<script> $(function () { // 设置鼠标放在验证码上,更换鼠标的形状 $('.captcha').css('cursor','pointer') $('.captcha').click(function () { showNewCode() }) }) function showNewCode(){ oldValue = false seconds = 3 timeInterval = null // 请求验证码地址,获取最新的验证码图片以及验证码内容 $.getJSON('/captcha/refresh/',function (data) { console.log(data) // attribute属性 // 更新验证码图片 $('.captcha').attr('src',data['image_url']) // 更新验证码的值 $('#id_captcha_0').val(data['key']) timeInterval = setInterval(function () { seconds -- $('#show').text(seconds + 's') if(seconds<0) { clearInterval(timeInterval) oldValue = true $('#show').text('') } },1000) }) }
$('#id_captcha_1').click(function () { if(oldValue == true) { alert('验证码已过期') showNewCode() } }) </script>
此时的结果如下:
这样,我们就完成了注册界面的设置,下面就是当用户注册的时候,我们需要将数据存储到数据库。然后在用户登录的时候,拿出来对比,若数据一样,那就可以登录成功,若数据不一样,则登录失败。
此时的views.py中注册代码如下:
from django.shortcuts import render from django.views import View from .forms import RegisterForm from .models import UserProfile from django.contrib.auth.hashers import make_password
class RegisterView(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(): # 从请求中获取email的值 email = request.POST['email'] # 从请求中获取password的值 password = request.POST['password'] # 判断是否有相同的账号在数据库中 user = UserProfile.objects.filter(email=email) if user: # 相同的话,注册失败,返回注册界面,同时返回注册失败的信息 return render(request,'register.html',{'register_form':register_form}) user = UserProfile() user.email = email # 利用哈希算法加密注册密码 user.password = make_password(password) user.is_active = 0 user.save() # send_email(email = email) return render(request,'tips.html') else: # 数据不合法 return render(request,'register.html',{'register_form':register_form})
tips.html文件中跳转界面的设置代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册成功的界面</title> </head> <body> <div> <span> 3 </span> 秒钟以后跳转到其他页面 </div> <a href="/login/login/">立即跳转</a> <script src="/static/js/jquery.js"></script> <script> // 设置3秒钟之后自动跳转界面 $(function () { var second = 3 setInterval(function () { second --; $('span').text(second + 's') if (second == 0) { window.location.href = '/login/login/' } },1000) }) </script> </body> </html>
界面显示结果如下:
此时界面需要跳转到登录界面,我们需要在myApp文件中的urls.py文件中做路由设置,代码如下:
from django.urls import path from .views import RegisterView,LoginView urlpatterns = [ path(r'register/',RegisterView.as_view(),name = 'register'), path(r'login/',LoginView.as_view(),name='login'), ]
然后在views.py文件中做界面返回处理,代码如下:
class LoginView(View): def get(self,request): return render(request,'login.html') def post(self,request): return render(request,'login.html')
新建login.html文件,这个界面即为我们的登陆界面。稍后再做处理。
此时我们完成了注册界面的跳转,还有很重要的一部分,即为我们在点击注册按钮,跳转界面的时候,我们想要实现一个自动给注册者的邮箱发送一封验证邮件,该怎么做处理呢?
首先,我们需要做一个发送邮件的设置,来到settings文件中,设置如下:
# 邮箱设置 EMAIL_HOST = 'smtp.qq.com' EMAIL_PORT =25 EMAIL_HOST_USER = 'xxxxxxxx' EMAIL_HOST_PASSWORD ='xxxx' # 开启安全连接 EMAIL_HOST_TLS = True
然后新建一个发送邮件的文件夹,如下:
代码如下: from django.core.mail import send_mail,EmailMultiAlternatives from django.conf import settings import random from myApp.models import EmailRecord def get_random_code(max_length=16): str = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890' content = '' for x in range(max_length): content = content + random.choice(str) # content = content +random.randint(0,len(str)-1) return content def send_email(code,email): if code==0 or code==None: code = get_random_code() # 获取随机的激活码 code = get_random_code() # 保存邮件信息 email_obj = EmailRecord() email_obj.code = code email_obj.email = email email_obj.save() email_subject = 'XX网账户激活通知' mail_content = '<h3>点击以下链接,激活账户:</h3><a href="http://localhost:8000/login/active/%s">http://localhost:8000/login/active/%s</a> '%(code,code) mail = EmailMultiAlternatives(email_subject,mail_content,settings.EMAIL_HOST_USER,['[email protected]',]) mail.content_subtype = 'html' res = mail.send() return res
然后将上面注册部分的那句
send_email(email = email)
解注释即可。
在发送邮箱之后,用户点击邮箱中的验证链接应该跳转到另一个页面,我们在models.py文件中做这样的设置:
class EmailRecord(models.Model): code = models.CharField(max_length=20,) send_date = models.DateTimeField(default = datetime.datetime.now(),) email = models.EmailField(error_messages={'invalid':'邮箱格式'},)
接下来,我们进行登录界面的设置。
模板代码如下:
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% block link %} {% endblock %} <link rel="stylesheet" href="/static/css/bootstrap.css"> <title>{% block title %}注册{% endblock %}</title> {% block style %} <style> .container{ margin-top: 60px; } .form-horizontal{ position: relative; left: -8%; } .captcha{ width: 80px; height: 40px; } #right{ position: relative; left: 200px; color: gray; } </style> {% endblock %} </head> <body> {% block main %} <div class="container"> <h2 class="text-center">请输入注册信息</h2> <form class="form-horizontal" role="form" action="{% url 'register' %}" method="POST"> {% csrf_token %} <div class="form-group"> <label for="inputEmail" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> <input name="email" type="text" class="form-control" id="inputEmail" placeholder="请输入邮箱"> </div> </div> <div class="form-group"> <label for="inputPassword" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input name="password" type="text" class="form-control" id="inputPassword" placeholder="请输入密码"> </div> </div> <div class="form-group" id="right"> <div class="col-sm-10"> {{register_form.captcha}} <label for="" id="show"></label> </div> </div> <div class="form-group"> <h3>{{register_form.errors.email}}</h3> <h3>{{register_form.errors.password}}</h3> <h3>{{register_form.errors.captcha}}</h3> <h3>{{msg}}</h3> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button id="submit" type="submit" class="btn btn-default btn-block btn-success">注册</button> </div> </div> </form> </div> {% endblock %} <script src="/static/js/jquery.js"></script> <script src="/static/js/bootstrap.js"></script> {% block script %} <script> $(function () { $('.captcha').css('cursor','pointer') $('.captcha').click(function () { showNewCode() }) }) function showNewCode(){ oldValue = false seconds = 3 timeInterval = null // 请求验证码地址,获取最新的验证码图片以及验证码内容 $.getJSON('/captcha/refresh/',function (data) { console.log(data) // attribute属性 // 更新验证码图片 $('.captcha').attr('src',data['image_url']) // 更新验证码的值 $('#id_captcha_0').val(data['key']) timeInterval = setInterval(function () { seconds -- $('#show').text(seconds + 's') if(seconds<0) { clearInterval(timeInterval) oldValue = true $('#show').text('') } },1000) }) } $('#id_captcha_1').click(function () { if(oldValue == true) { alert('验证码已过期') showNewCode() } }) </script> {% endblock %} </body> </html>
登录界面继承自母模板,代码如下:
{% extends 'base.html' %} {% block main %} <div class="container"> <h2 class="text-center">请输入登录信息</h2> <form class="form-horizontal" role="form" action="{% url 'login' %}" method="POST"> {% csrf_token %} <div class="form-group"> <label for="inputEmail" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> <input name="email" type="text" class="form-control" id="inputEmail" placeholder="请输入邮箱"> </div> </div> <div class="form-group"> <label for="inputPassword" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input name="password" type="text" class="form-control" id="inputPassword" placeholder="请输入密码"> </div> </div> <div class="form-group"> <h3>{{register_form.errors.email}}</h3> <h3>{{register_form.errors.password}}</h3> <h3>{{msg}}</h3> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button id="submit" type="submit" class="btn btn-default btn-block btn-success">登录</button> </div> </div> </form> </div> {% endblock %}
报错信息:
UNIQUE constraint failed: myApp_userprofile.username
当我们第二次注册的时候,会报这个错误,这时,需要在注册的函数中添加这样一句话:
user.username = email
即可以解决这个问题。
刷新登录界面,如图:
在登录的时候,我们需要通过forms来验证对照输入的账号和密码,在forms.py文件中做如下设置:
class LoginForm(forms.Form): email = forms.EmailField(required=True,error_messages={'invalid':'邮箱格式不正确'}) password = forms.CharField(min_length=6,required=True,error_messages={'min_length':'密码长度少于6'})
重新迁移文件。
即可完成邮件发送功能。
然后在视图文件中写登录代码:
class LoginView(View): def get(self, request): return render(request, 'login.html') def post(self,request): login_form = LoginForm(request.POST) if login_form.is_valid(): email = request.POST['email'] password = request.POST['password'] # user = UserProfile.objects.get(email=email) # 验证账号密码是否一致 # user = authenticate(email=email,password=password) user = UserProfile.objects.get(email=email) result = check_password(password,user.password) if result: if user.is_active == 1: return render(request,'home.html') else: code_obj = EmailRecord.objects.get(email=email) code = code_obj.code send_email(email,code) return render(request,'login.html',{'login_form':login_form,'msg':'该账号尚未被激活,请前往邮箱进行激活'}) else: return render(request,'login.html',{'login_form':login_form,'msg':'账号密码不匹配,请核对'}) else: return render(request,'login.html',{'login_form':login_form})
最后剩下一个激活码激活跳转到登录页面的功能。
视图文件代码如下:
class ActiveView(View): def get(self,request,code): try: # 根据指定的激活码,找到对应的邮箱 email_code = EmailRecord.objects.get(code=code) except Exception as e: # 如果邮箱没有被找到, return render(request,'activefile.html') else: # 如果邮箱被找到 user = UserProfile.objects.get(email=email_code.email) user.is_active = 1 user.save() return render(request,'login.html') def post(self,request,code): return render(request,'page.html')
myApp中路由设置为:
from django.conf.urls import url urlpatterns = [ url(r'active/(?P<code>\w+)/', ActiveView.as_view(), name='active') ]
此时,我们就完成了所有的功能。