前言
使用IDE:PyCharm
操作系统:Mac
Python的版本:3.6
我的邮箱:51263921@qq.com
交流群:372430835
说明:
本次课程的GitHub代码在最下面。
本次课程基于上个课程的代码,如果没看过的请先传送:
使用Python的瓶框架开发的Web网站系列课程(一)构建项目
使用Python的瓶框架开发的Web网站系列课程(二)注册功能
一、登录
本次课程主要实现登录,我们按照实际开发的流程,先看到登录页面,再尝试页面传值(也就是输入账号密码)到服务端,服务端校验和鉴权,并跳转页面。
1.1增加backend.account.views关于登录的代码
全路径:/myproject/backend/account/views.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/22 上午9:40.
"""
from flask import Blueprint,request,render_template,jsonify,flash #第二课增加内容
from backend.models.UserModel import User
from backend.models import db
#账户的蓝图 访问http://host:port/account 这个链接的子链接,都会跳到这里
account = Blueprint('/account', __name__) #第二课增加内容
# 访问http://host:port/account/register 这个链接,就会跳到这里
@account.route('/register',methods=(["GET","POST"])) #第二课增加内容
#上面的链接,绑定的就是这个方法,我们给浏览器或者接口请求 一个json格式的返回
def register(): #第二课增加内容
if request.method == 'POST':
form = request.form
user = User(username=form['username'],email=form['email'],password=form['password'])
db.session.add(user)
db.session.commit()
return jsonify(form)
return render_template('/account/register.html')
@account.route('/login',methods=(["GET","POST"]))
def login(): #第三课内容
if request.method == "POST":
return jsonify(request.form)
return render_template('/account/login.html')
1.2增加html页面文件
全路径:/myproject/frontend/account/login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>INSPINIA | Login</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/animate.css/3.5.2/animate.css" rel="stylesheet">
<link href="../static/css/style.css" rel="stylesheet">
</head>
<body class="gray-bg">
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<div>
<h1 class="logo-name">IN+</h1>
</div>
<h3>Welcome to IN+</h3>
<p>Perfectly designed and precisely prepared admin theme with over 50 pages with extra new web app views.
<!--Continually expanded and constantly improved Inspinia Admin Them (IN+)-->
</p>
<p>Login in. To see it in action.</p>
<form class="m-t" role="form" action="/account/login" method="post">
<div class="form-group">
<input type="text" class="form-control" name="username" placeholder="Username" required="">
</div>
<div class="form-group">
<input type="password" class="form-control" name="password" placeholder="Password" required="">
</div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-success">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
{% endif %}
{% endwith %}
<button type="submit" class="btn btn-primary block full-width m-b">Login</button>
<a href="#"><small>Forgot password?</small></a>
<p class="text-muted text-center"><small>Do not have an account?</small></p>
<a class="btn btn-sm btn-white btn-block" href="register.html">Create an account</a>
</form>
<p class="m-t"> <small>Inspinia we app framework base on Bootstrap 3 © 2014</small> </p>
</div>
</div>
<!-- Mainly scripts -->
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.js"></script>
</body>
</html>
1.3 测试一把
点击login后显示如下的话,表示成功。
{
"password": "abc123",
"username": "admin"
}
1.4 修改backend.account.view 增加鉴权代码
1.4.1 装个包 pip install Flask-Login==0.4.1
1.4.2 修改 /myproject/backend/view.py 注意修改文件的路径
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/21 下午3:51.
"""
from flask_login import LoginManager #第三课新增
# Set up Flask-Login
login_manager = LoginManager() #第三课新增
login_manager.session_protection = 'strong' #第三课新增
login_manager.login_view = 'account.login' #第三课新增
1.4.3 修改/myproject/backend/__init__.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/21 下午2:41.
"""
import os
from flask import Flask
from config.config import config
from backend.urls import register
from backend.models import db #第二课增加内容
from backend.views import login_manager #第三课增加内容
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_TEMPLATE_FOLDER = os.path.join(BASE_DIR,'frontend')
def create_app():
#初始化项目实例
app = Flask(__name__,template_folder=BASE_TEMPLATE_FOLDER,static_folder=os.path.join(BASE_DIR,'frontend','static'))
app.secret_key = app.config['SECRET_KEY']
#导入配置项
app.config.from_object(config)
# 注册路由
register(app)
# 注册数据库
db.init_app(app) #第二课增加内容
#注册登录组件
login_manager.init_app(app) #第三课增加内容
# 钩子 在请求执行之前
@app.before_request
def before_request():
print('hi')
return app
1.4.4 修改/myproject/backend/account/views.py
这里和之前的区别是增加了鉴权的内容,判断用户名和密码是否为空,判断密码对不对。增加了登出的功能。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/22 上午9:40.
"""
from flask import Blueprint,request,render_template,jsonify,flash #第二课增加内容
from flask import redirect,url_for,current_app
from backend.models.UserModel import User
from backend.models import db
from flask_login import login_user,login_required,logout_user #第三课增加内容
#账户的蓝图 访问http://host:port/account 这个链接的子链接,都会跳到这里
account = Blueprint('account', __name__) #第二课增加内容
# 访问http://host:port/account/register 这个链接,就会跳到这里
@account.route('/register',methods=(["GET","POST"])) #第二课增加内容
#上面的链接,绑定的就是这个方法,我们给浏览器或者接口请求 一个json格式的返回
def register(): #第二课增加内容
if request.method == 'POST':
form = request.form
user = User(username=form['username'],email=form['email'],password=form['password'])
db.session.add(user)
db.session.commit()
return jsonify(form)
return render_template('/account/register.html')
@account.route('/login',methods=(["GET","POST"]))
def login(): #第三课内容
if request.method == "POST":
form = request.form #获取登录表单
user = User.query.filter_by(username=form['username']).first() #查出用户信息
if user is not None and user.password_hash is not None and user.verify_password(form['password']): #检查密码是否正确
login_user(user,True) #登录操作
flash('You are now logged in. Welcome back!', 'success')
return redirect( url_for(request.args.get('next') or 'admin.index'))
else:
flash('Invalid email or password.', 'error')
return render_template('/account/login.html')
@account.route('/logout')
@login_required
def logout():
logout_user()
flash('You have been logged out.', 'info')
return redirect(url_for('admin.index'))
1.4.5 调整一下我们的/myproject/backend/models/UserModel.py
增加了鉴权模块需要的东西,知识点可以百度flask_login的user_loader和anonymous_user
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/22 下午1:50.
"""
from flask_login import UserMixin,AnonymousUserMixin #第二课增加内容
from werkzeug.security import check_password_hash, generate_password_hash #第二课增加内容
from backend.models import db #第二课增加内容
from backend.views import login_manager #第三课新增
class User(UserMixin, db.Model): #第二课增加内容
__tablename__ = 'users' #这是我们将来建出来的表的表名,在这里定义,下面的都是字段名和字段类型长度这些
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True)
email = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
#脱敏
@property
def password(self): #第二课增加内容
raise AttributeError('`password` is not a readable attribute')
#加密
@password.setter
def password(self, password): #第二课增加内容
self.password_hash = generate_password_hash(password)
#校验密码
def verify_password(self, password): #第二课增加内容
return check_password_hash(self.password_hash, password)
#查询返回的格式
def __repr__(self): #第二课增加内容
return '<User \'%s\'>' % self.username
class AnonymousUser(AnonymousUserMixin): #第三课新增
def can(self, _):
return False
def is_admin(self):
return False
login_manager.anonymous_user = AnonymousUser #第三课新增
@login_manager.user_loader
def load_user(user_id): #第三课新增
return User.query.get(int(user_id))
1.4.6 增加前端目录和页面
先建文件夹
全路径:/myproject/frontend/base
新增页面html文件layout.html
/myproject/frontend/base/layout.html
内容为:
<!doctype html>
<title>My Application</title>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
新增页面html文件index.html
/myproject/frontend/base/index.html
{% extends "base/layout.html" %}
{% block body %}
<h1>Overview</h1>
{% if current_user.is_authenticated %}
<p>welcome ~ <a href="/account/logout">logout</a>
{% else %}
<p>Do you want to <a href="/account/login">log in?</a>
{% endif %}
{% endblock %}
1.4.7 新增后端文件夹和文件
在/myproject/backend/下新增文件夹 admin
全路径: /myproject/backend/admin
在admin下新增__init__.py和views.py
/myproject/backend/admin/__init__.py内容为空
全路径:/myproject/backend/admin/views.py
内容如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/23 上午11:09.
"""
from flask import Blueprint,render_template
from backend.account.views import login_required
admin = Blueprint('admin', __name__)
@admin.route('/')
def index():
return render_template('/base/index.html')
二,测试登录
访问http://127.0.0.1:10101/admin/
显示内容为,意思就是你没登录,让你点登录:
概观
你想 登录吗?
点击后跳转页面,到我们一开始做的登录页面,网址为http://127.0.0.1:10101/account/login
输入账号密码登录,成功的话跳转回一开始的页面,但是显示内容变了:
- 您现在已登录。欢迎回来!
概观
欢迎〜 注销
是不是很简单〜
三,本课代码
github:https: //github.com/lyy8510a/myproject/releases/tag/v3