1.1 创建项目和app
django-admin startproject mysite_loginpython ** nage.py startapp login1. 设置时区和语言 settings.py文件中
LANGUAGE_CODE = 'zh-hans'TIME_ZONE = 'Asia/Shanghai'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = False1.3 测试项目 启动 在浏览器中输入 http://127.0.0.1:8000/
2.1.数据库模型设计(用户表User ---> 用户名 密码 电子邮件地址 性别 创建时间)
# -*- coding:utf-8 -*-from django.db import models# login/models.pyclass User(models.Model): '''用户表''' gender = ( (' ** le','男'.), ('fe ** le','女'、 ) name = models.CharField( ** x_length=128) #name必填,最长不超过128个字符 password = models.CharField( ** x_length=256) e ** il = models.E ** ilField(unique=True) #e ** il使用Django内置邮箱类型,唯一的 ** = models.CharField( ** x_length=32,choices=gender,default='男'.) #性别使用了一个choice,只能选择男女,默认为男 c_time = models.DateTimeField(auto_now_add=True) def __str__(self): #使用__str__有助于人性化显示对象信息 return self.name class Meta: ordering = ['c_time'.verbose_name = '用户'. verbose_name_plural = '用户'. db_table = 'user'2.2.设置数据库为Mysql在settings.py修改)
DATABASES = 'default': #'ENGINE': 'django.db.backends.sqlite3'、 #'NAME': os.path.join(BASE_DIR,'db.sqlite3'.), 'ENGINE': 'django.db.backends.mysql'、 'NAME': 'django',# database name 'USER': 'root'、 'PASSWORD': 'admin'、 'HOST': '127.0.0.1', #IP 'PORT': '3306'、 #端口#安装数据库驱动,Python3.驱动程序有多种选择。例如,有pymysql以及mysqlclient
ps: 如果安装了pymysql 需要在那里logininit.py里面导入pymysql模块# login/init.pyimport pymysqlpymysql.install_as_MySQLdb()如果是安装的话mysqlclient 不需要上述操作2.3.数据库迁移
迁移到数据库(ps: 数据库迁移前必须注册 app Django可添加创建项目app直接帮你setting.py 中注册)python ** nage.py ** kemigrationspython ** nage.py migrate-------------------------------------如果是在pycharm操作 先 ctrl alt R 进入命令模式** nage.py@mysite_login > ** nage.py@mysite_login > ** kemigrations ** nage.py@mysite_login > migrate3.2.创建超级管理员
python ** nage.py createsuperuser----------------------------------- ** nage.py@mysite_login > createsuperuser然后增加几个测试用户 跟随提示 假设创建了 test snow dorra 开发3个超级管理员账户 python ** nage.py runserver在浏览器中输入 http://127.0.0.1:8000/admin 进入后台登录页面4.1.路由设计 (这里没有二级路由,而是直接在根路由下编写路由条目)
4.2. 初步实现架构(login/views.py)
from django.shortcuts import render,redirect# login/views.pydef index(request): pass return render(request,'login/index.html')def login(request): pass return render(request,'login/login.html')def register(request): pass return render(request,'login/register.html')def logout(request): pass return redirect('/index/')4.3.创建HTML页面文件
项目根路径login在目录中创建一个templates目录,再在templates在目录中创建一个login目录在login/templates/login在目录中创建三个文件index.html、login.html以及register.html ,并写下以下代码:{#login/templates/login/index.html#}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首页</title></head><body><h1>首页</h1></body></html>login.html{#login/templates/login/login.html#}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>登录</title></head><body><h1>登录页面</h1></body></html>register.html{#login/templates/login/register.html#}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>注册</title></head><body><h1>注册页面</h1></body></html> 5.1.原生HTML页面 (login.html文件内容如下){#login/templates/login/login.html#}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>登录</title></head><body> <div style=" ** rgin: 15% 40%;"> <h1>欢迎登录!</h1> <form action="/login/" method="post"> <p> <label for="id_username">用户名:</label> <input type="text" id="id_username" name="username" placeholder="用户名" autofocus required /> </p> <p> <label for="id_password">密码:</label> <input type="password" id="id_password" placeholder="密码" name="password" required > </p> <input type="submit" value="确定"> </form> </div></body></html>5.2.引入Bootstrap
https://v3.bootcss.com/getting-started/#download Bootstrap3.3.7 下载地址
根目录下新建一个static目录,并将解压后的bootstrap-3.3.7-dist目录,整体拷贝到static目录中,如下图所示:
由于Bootstrap依赖JQuery,所以我们需要提前下载并引入JQuery 下载地址
在static目录下,新建一个css和js目录,作为以后的样式文件和js文件的存放地,将我们的jquery文件拷贝到static/js目录下。
然后打开项目的settings文件,在最下面添加配置,用于指定静态文件的搜索目录:STATIC_URL = '/static/'STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"),]5.3.创建base.html模板
既然要将前端页面做得像个样子,那么就不能和前面一样,每个页面都各写各的,单打独斗。一个网站有自己的统一风格和公用部分,可以把这部分内容集中到一个基础模板base.html中。现在,在根目录下的templates中新建一个base.html文件用作站点的基础模板。在Bootstrap文档中,为我们提供了一个非常简单而又实用的基本模板,代码如下:<!DOCTYPE html><html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>Bootstrap 101 Template</title> <!-- Bootstrap --> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <h1>你好,世界!</h1> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="js/bootstrap.min.js"></script> </body></html>将它整体拷贝到base.html文件中。5.4.创建页面导航条 (https://v3.bootcss.com/getting-started/#download) 看Bootstrap 源码中的文档
Bootstrap提供了现成的导航条组件
<nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --></nav>其中有一些部分,比如搜索框是我们目前还不需要的,需要将多余的内容裁剪掉。同时,有一些名称和url地址等需要按我们的实际内容修改。最终导航条的代码如下:
<nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav" aria-expanded="false"> <span class="sr-only">切换导航条</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Mysite</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="my-nav"> <ul class="nav navbar-nav"> <li class="active"><a href="/index/">主页</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login/">登录</a></li> <li><a href="/register/">注册</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>5.5.使用Bootstrap静态文件
{% static '相对路径' %}这个Django为我们提供的静态文件加载方法,可以将页面与静态文件链接起来 最后,base.html内容如下:
{% load staticfiles %}<!DOCTYPE html><html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>{% block title %}base{% endblock %}</title> <!-- Bootstrap --> <link href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> {% block css %}{% endblock %} </head> <body> <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav" aria-expanded="false"> <span class="sr-only">切换导航条</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Mysite</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="my-nav"> <ul class="nav navbar-nav"> <li class="active"><a href="/index/">主页</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login/">登录</a></li> <li><a href="/register/">注册</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> {% block content %}{% endblock %} <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="{% static 'js/jquery-3.2.1.js' %}"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> </body></html>简要说明:
看下效果
5.6.设计登录页面
Bootstarp提供了一个基本的表单样式,代码如下:
<form> <div class="form-group"> <label for="exampleInputE ** il1">E ** il address</label> <input type="e ** il" class="form-control" id="exampleInputE ** il1" placeholder="E ** il"> </div> <div class="form-group"> <label for="exampleInputPassword1">Password</label> <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password"> </div> <div class="form-group"> <label for="exampleInputFile">File input</label> <input type="file" id="exampleInputFile"> <p class="help-block">Example block-level help text here.</p> </div> <div class="checkbox"> <label> <input type="checkbox"> Check me out </label> </div> <button type="submit" class="btn btn-default">Submit</button></form>我们结合Bootstrap和前面自己写的form表单,修改login/templates/login/login.html成符合项目要求的样子:
{% extends 'base.html' %}{% load staticfiles %}{% block title %}登录{% endblock %}{% block css %} <link rel="stylesheet" href="{% static 'css/login.css' %}">{% endblock %}{% block content %} <div class="container"> <div class="col-md-4 col-md-offset-4"> <form class='form-login' action="/login/" method="post"> <h2 class="text-center">欢迎登录</h2> <div class="form-group"> <label for="id_username">用户名:</label> <input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required> </div> <div class="form-group"> <label for="id_password">密码:</label> <input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required> </div> <button type="reset" class="btn btn-default pull-left">重置</button> <button type="submit" class="btn btn-pri ** ry pull-right">提交</button> </form> </div> </div> <!-- /container -->{% endblock %}说明:
通过{% extends 'base.html' %}继承了‘base.html’模板的内容;通过{% block title %}登录{% endblock %}设置了专门的title;通过block css引入了针对性的login.css样式文件;主体内容定义在block content内部添加了一个重置按钮。在static/css目录中新建一个login.css样式文件,这里简单地写了点样式,
body { background-color: #eee;}.form-login { ** x-width: 330px; padding: 15px; ** rgin: 0 auto;}.form-login .form-control { position: relative; height: auto; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 10px; font-size: 16px;}.form-login .form-control:focus { z-index: 2;}.form-login input[type="text"] { ** rgin-bottom: -1px; border-bottom-right-radius: 0; border-bottom-left-radius: 0;}.form-login input[type="password"] { ** rgin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0;}最后效果
6.1.登录视图根据我们在路由中的设计,用户通过login.html中的表单填写用户名和密码,并以POST的方式发送到服务器的/login/地址。服务器通过login/views.py中的login()视图函数,接收并处理这一请求。
我们可以通过下面的方法接收和处理请求:
def login(request): if request.method == "POST": username = request.POST.get('username') password = request.POST.get('password') print(username, password) return redirect('/index/') # POST 请求过来 跳转到index页面 return render(request,'login/login.html')还需要在前端页面的form表单内添加一个{% csrf_token %}标签:
<form class='form-login' action="/login/" method="post"> {% csrf_token %} <h2 class="text-center">欢迎登录</h2> <div class="form-group"> ......</form>进入登录页面,输入用户名,密码然后跳转到index页面。
6.2.数据验证通过唯一的用户名,使用Django的ORM去数据库中查询用户数据,如果有匹配项,则进行密码对比,如果没有匹配项,说明用户名不存在。如果密码对比错误,说明密码不正确。
from .models import Userdef login(request): if request.method == "POST": username = request.POST.get('username', None) password = request.POST.get('password', None) if username and password: # 确保用户名和密码都不为空 username = username.strip() # 用户名字符合法性验证 # 密码长度验证 # 更多的其它验证..... try: #from .models import User user = User.objects.get(name=username) print("user ", user) except: return render(request, 'login/login.html') if user.password == password: return redirect('/index/') return render(request, 'login/login.html')6.3.添加提示信息上面的代码还缺少很重要的一部分内容,提示信息!无论是登录成功还是失败,用户都没有得到任何提示信息,这显然是不行的。
修改一下login视图:
def login(request): if request.method == "POST": username = request.POST.get('username', None) password = request.POST.get('password', None) message = "所有字段都必须填写!" if username and password: # 确保用户名和密码都不为空 username = username.strip() # 用户名字符合法性验证 # 密码长度验证 # 更多的其它验证..... try: user = User.objects.get(name=username) if user.password == password: return redirect('/index/') else: message = "密码不正确!" except: message = "用户名不存在!" return render(request, 'login/login.html', {"message": message}) return render(request, 'login/login.html')增加了message变量,用于保存提示信息。当有错误信息的时候,将错误信息打包成一个字典,然后作为第三个参数提供给render()方法。这个数据字典在渲染模板的时候会传递到模板里供你调用。
为了在前端页面显示信息,还需要对login.html进行修改:
{% extends 'login/base.html' %}{% load staticfiles %}{% block title %}登录{% endblock %}{% block css %} <link rel="stylesheet" href="{% static 'css/login.css' %}">{% endblock %}{% block content %} <div class="container"> <div class="col-md-4 col-md-offset-4"> <form class='form-login' action="/login/" method="post"> {% if message %} <div class="alert alert-warning">{{ message }}</div> {% endif %} {% csrf_token %} <h2 class="text-center">欢迎登录</h2> <div class="form-group"> <label for="id_username">用户名:</label> <input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required> </div> <div class="form-group"> <label for="id_password">密码:</label> <input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required> </div> <button type="reset" class="btn btn-default pull-left">重置</button> <button type="submit" class="btn btn-pri ** ry pull-right">提交</button> </form> </div> </div> <!-- /container -->{% endblock %}把index.html主页模板也修改一下,删除原有内容,添加下面的代码:
{#login/templates/login/index.html#}{% extends 'base.html' %}{% block title %}主页{% endblock %}{% block content %} <h1>欢迎回来!</h1>{% endblock %}Django的表单给我们提供了下面三个主要功能:
准备和重构数据用于页面渲染;为数据创建HTML表单元素;接收和处理用户从表单发送过来的数据7.1.创建表单模型# -*- coding:utf-8 -*-from django import forms# 在 login/ 新建 UserForm.pyclass UserForm(forms.Form): username = forms.CharField(label="用户名", ** x_length=128) password = forms.CharField(label="密码", ** x_length=256, widget=forms.PasswordInput)说明:
要先导入forms模块所有的表单类都要继承forms.Form类每个表单字段都有自己的字段类型比如CharField,它们分别对应一种HTML语言中<form>内的一个input元素。这一点和Django模型系统的设计非常相似。label参数用于设置<label>标签 ** x_length限制字段输入的最大长度。它同时起到两个作用,一是在浏览器页面限制用户输入不可超过字符数,二是在后端服务器验证用户输入的长度也不可超过。widget=forms.PasswordInput用于指定该字段在form表单里表现为<input type='password' />,也就是密码输入框。 7.2.修改视图使用了Django的表单后,就要在视图中进行相应的修改:
# login/views.py 部分代码from .UserForm import UserFormdef login(request): if request.method == "POST": login_form = UserForm(request.POST) message = "请检查填写的内容!" if login_form.is_valid(): username = login_form.cleaned_data['username'] password = login_form.cleaned_data['password'] try: user = User.objects.get(name=username) if user.password == password: return redirect('/index/') else: message = "密码不正确!" except: message = "用户不存在!" return render(request, 'login/login.html', locals()) login_form = UserForm()#GET方法请求页面,返回空的表单,让用户可以填入数据 return render(request, 'login/login.html', locals())说明:
对于非POST方法发送数据时,比如GET方法请求页面,返回空的表单,让用户可以填入数据;对于POST方法,接收表单数据,并验证;使用表单类自带的is_valid()方法一步完成数据验证工作;验证成功后可以从表单对象的cleaned_data数据字典中获取表单的具体值;如果验证不通过,则返回一个包含先前数据的表单给前端页面,方便用户修改。也就是说,它会帮你保留先前填写的数据内容,而不是返回一个空表!另外,这里使用了一个小技巧,Python内置了一个locals()函数,它返回当前所有的本地变量字典,我们可以偷懒的将这作为render函数的数据字典参数值,就不用费劲去构造一个形如{'message':message, 'login_form':login_form}的字典了。这样做的好处当然是大大方便了我们,但是同时也可能往模板传入了一些多余的变量数据,造成数据冗余降低效率。
7.3.修改login界面Django的表单很重要的一个功能就是自动生成HTML的form表单内容。现在,我们需要修改一下原来的login.html文件:
{% extends 'base.html' %}{% load staticfiles %}{% block title %}登录{% endblock %}{% block css %}<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}{% block content %} <div class="container"> <div class="col-md-4 col-md-offset-4"> <form class='form-login' action="/login/" method="post"> {% if message %} <div class="alert alert-warning">{{ message }}</div> {% endif %} {% csrf_token %} <h2 class="text-center">欢迎登录</h2> {{ login_form }} <button type="reset" class="btn btn-default pull-left">重置</button> <button type="submit" class="btn btn-pri ** ry pull-right">提交</button> </form> </div> </div> <!-- /container -->{% endblock %}浏览器生成的HTML源码
重新启动服务器,刷新页面,如下图所示:
7.4.手动渲染表单直接{{ login_form }}虽然好,啥都不用操心,但是界面真的很丑,往往并不是你想要的,如果你要使用CSS和JS,比如你要引入Bootstarps框架,这些都需要对表单内的input元素进行额外控制,那怎么办呢?手动渲染字段就可以了。
可以通过{{ login_form.name_of_field }}获取每一个字段,然后分别渲染,修改后的login.html如下:
{% extends 'base.html' %}{% load staticfiles %}{% block title %}登录{% endblock %}{% block css %}<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}{% block content %} <div class="container"> <div class="col-md-4 col-md-offset-4"> <form class='form-login' action="/login/" method="post"> {% if message %} <div class="alert alert-warning">{{ message }}</div> {% endif %} {% csrf_token %} <h2 class="text-center">欢迎登录</h2>{# {{ login_form }}#} <div class="form-group"> {{ login_form.username.label_tag }} {{ login_form.username}} </div> <div class="form-group"> {{ login_form.password.label_tag }} {{ login_form.password }} </div> <button type="reset" class="btn btn-default pull-left">重置</button> <button type="submit" class="btn btn-pri ** ry pull-right">提交</button> </form> </div> </div> <!-- /container -->{% endblock %}然后,在UserForm.py类里添加attr属性即可,如下所示修改login/UserForm.py
from django import forms# 在 filename UserForm.pyclass UserForm(forms.Form): username = forms.CharField(label="用户名", ** x_length=128, widget=forms.TextInput(attrs={'class': 'form-control'})) password = forms.CharField(label="密码", ** x_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))再次刷新页面,就显示正常了!
为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能。验证码(CAPTCHA)是“Completely Auto ** ted Public Turing test to tell Computers and Hu ** ns Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发这个库叫做django- ** -captcha。
8.1.安装captcha直接安装:pip install django- ** -captcha
注册captcha
在settings中,将‘captcha’注册到app列表里:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'login', 'captcha',]captcha需要在数据库中建立自己的数据表,所以需要执行migrate命令生成数据表:
python ** nage.py migrate
8.2.添加url路由根目录下的urls.py文件中增加captcha对应的网址:
from django.contrib import adminfrom django.urls import pathfrom login import viewsfrom django.conf.urls import include# mysite_login/urls.pyurlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), path('login/', views.login), path('register/', views.register), path('logout/', views.logout), path('captcha', include('captcha.urls')) # 增加这一行]8.3.修改UserForm.py如果上面都OK了,就可以直接在我们的UserForm.py文件中添加CaptchaField了。
# -*- coding:utf-8 -*-from django import formsfrom captcha.fields import CaptchaField# 在 login/ 新建 UserForm.pyclass UserForm_v1(forms.Form): username = forms.CharField(label="用户名", ** x_length=128) password = forms.CharField(label="密码", ** x_length=256, widget=forms.PasswordInput)class UserForm_v2(forms.Form): username = forms.CharField(label="用户名", ** x_length=128, widget=forms.TextInput(attrs={'class': 'form-control'})) password = forms.CharField(label="密码", ** x_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))class UserForm(forms.Form): username = forms.CharField(label="用户名", ** x_length=128, widget=forms.TextInput(attrs={'class': 'form-control'})) password = forms.CharField(label="密码", ** x_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'})) captcha = CaptchaField(label='验证码')需要提前导入from captcha.fields import CaptchaField,然后就像写普通的form字段一样添加一个captcha字段就可以了!
8.4.修改login.html由于我们前面是手动生成的form表单,所以还要修改一下login.html,添加captcha的相关内容,如下所示:
{% extends 'base.html' %}{% load staticfiles %}{% block title %}登录{% endblock %}{% block css %} <link rel="stylesheet" href="{% static 'css/login.css' %}">{% endblock %}{% block content %} <div class="container"> <div class="col-md-4 col-md-offset-4"> <form class='form-login' action="/login/" method="post"> {% if message %} <div class="alert alert-warning">{{ message }}</div> {% endif %} {% csrf_token %} <h2 class="text-center">欢迎登录</h2> <div class="form-group"> {{ login_form.username.label_tag }} {{ login_form.username}} </div> <div class="form-group"> {{ login_form.password.label_tag }} {{ login_form.password }} </div> <div class="form-group"> {{ login_form.captcha.errors }} {{ login_form.captcha.label_tag }} {{ login_form.captcha }} </div> <button type="reset" class="btn btn-default pull-left">重置</button> <button type="submit" class="btn btn-pri ** ry pull-right">提交</button> </form> </div> </div> <!-- /container -->{% endblock %}这里额外增加了一条{{ login_form.captcha.errors }}用于明确指示用户,你的验证码不正确.
扫码咨询与免费使用
申请免费使用