flask框架网页(Python Flask框架-开发简单博客-认证蓝图)
作者:Eason_LYC
悲观者预言失败 ,十言九中 。 乐观者创造奇迹 ,一次即可 。
一个人的价值 ,在于他所拥有的 。可以不学无术 ,但不能一无所有!
技术领域:WEB安全 、网络攻防
关注WEB安全 、网络攻防 。我的专栏文章知识点全面细致 ,逻辑清晰 、结合实战 ,让你在学习路上事半功倍 ,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上 ,这是我们理想中的极乐世界~(关注我即可加入社区)本专栏是对Flask官方文档中个人博客搭建进行的归纳总结 ,与官方文档结合事半功倍 。基础薄弱的同学请戳Flask官方文档教程
本人经验 ,学习一门语言或框架时 ,请首先阅读官方文档 。学习完毕后 ,再看其他相关文章(如本系列文章),才是正确的学习道路 。
如果Python都完全不熟悉 ,一定不要着急学习框架 ,请首先学习python官方文档,一步一个脚印 。要不然从入门到放弃是大概率事件 。
Python 官方文档教程本系列已发布文章:
Python Flask框架-开发简单博客-开篇介绍 Python Flask框架-开发简单博客-项目布局 、应用设置 Python Flask框架-开发简单博客-定义和操作数据库1. 本章知识点总结
2. 蓝图功能分析
flask框架中蓝图注册分为两步 ,第一步新建蓝图模块 ,第二步在工厂函数中注册蓝图 。
auth.py的作用: auth蓝图部分的视图代码实现
auth模块用于认证相关工作 ,访问路径问 “/auth/函数名 ” 。主要功能包括:注册 、登陆 、验证session 、注销 、判断已登录的装饰器 。 注册:用户点击注册 ,输入拟注册的用户名和密码 ,前后端均验证。通过后跳转至登陆页面 。 登陆:用户点击登录 ,输入用户名和密码 ,前后端均验证 。通过后完成登陆 ,生成并保存session。以登录用户的身份浏览博客; 验证session:用户登录首页 ,先判断是否有session,若有则从数据库提取对应用户信息 ,以登录用户的身份浏览博客; 注销:用户点击注销 ,删除session ,退出登陆状态 。 判断已登录的装饰器:各页面对是否登录的浏览者展现内容略有不同,通过此装饰器实现后台的自动判断 ,区别响应登陆或未登录的浏览者代码所需库
仅是为了后续查找学习方便 ,在此处列出 。实际代码开发中,是在写代码时 ,需要用到哪个库 ,逐步添加即可 。
flaskr/auth.py
import functools from flask import Blueprint, request, render_template, flash, session, redirect, url_for, g from werkzeug.security import generate_password_hash, check_password_hash from flaskr.db import get_db文件结构
3. 蓝图创建和注册
在flaskr文件夹下新建auth.py ,创建一个名称为 ‘auth’ 的 Blueprint 。和应用对象一样 , 蓝图需要知道是在哪里定义的 ,因此把 name 作为函数的第二个参数 。 url_prefix 会添加到所有与该蓝图关联的 URL 前面 。
flaskr/auth.py
# 1. 注册蓝图 bp = Blueprint(auth, __name__, url_prefix=/auth)使用 app.register_blueprint() 导入并注册 蓝图 。
flaskr/init.py
def create_app(): app = ... # 之前的代码 # 本次新增的代码 ,蓝图注册 from . import auth app.register_blueprint(auth.bp) return app # 之前的代码4. auth视图功能实现
主要功能包括:注册(register) 、登陆(login) 、验证session(load_logged_in_user) 、注销(logout) 、判断已登录的装饰器(login_required) 。
4.1 实现注册(register)视图
当用访问 /auth/register URL 时 , register 视图会返回用于填写注册内容的表单的 HTML 。当用户提交表单时 ,视图会验证表单内容 ,然后要么再次显示表单并显示一个出错信息 ,要么创建新用户并显示登录页面 。
现在只是编写视图代码 ,在下一页会编写生成 HTML 表单的模板 。
flaskr/auth.py
@bp.route(/register, methods=(GET, POST)) def register(): # POST访问方式 ,进入表单与数据库的注册后台逻辑 if request.method == POST: username = request.form[username] password = request.form[password] db = get_db() error = None # 后端验证username、password是否缺失 if not username: error = 用户名不能为空! elif not password: error = 密码不能为空! # 通过验证后,查询数据库 ,无错误时写入数据 ,完成注册 。有错误反馈。 if error is None: try: db.execute( "INSERT INTO user (username, password) VALUES (?, ?)", (username, generate_password_hash(password)), ) db.commit() except db.IntegrityError: error = f用户 {username} 已经注册过! else: return redirect(url_for(auth.login)) # 页面闪现错误提示 flash(error) # GET访问方式,直接返回注册页面 return render_template(auth/register.html)@bp.route 作用
关联了 URL /register 和 register 视图函数 。当 Flask 收到一个指向 /auth/register 的请求时就会调用 register 视图并把其返回值作为响应 。request.form
是一个特殊类型的 dict ,其映射了提交表单的键和值。表单中 ,用户将会输入其 username 和 password 。验证 username 和 password 不为空 。如果验证成功 ,就把新用户的数据插入数据库 。
db.execute
使用了带有 ? 占位符的 SQL 查询语句 。
占位符可以代替后面的元组参数中相应的值 。使用占位符的好处是会自动帮你转义输入值 ,以抵御 SQL 注入攻击 。generate_password_hash()
因为安全原因 ,不能把密码明文储存在数据库中 。而是应当使用 generate_password_hash() 生成安全的哈希值 , 再把哈希值储存到数据库中 。因为查询修改了数据 ,所以要使用 db.commit() 保存修改 。如果用户名已存在 ,会产生一个 sqlite3.IntegrityError 错误 , 应当将该错误作为一个验证错误显示给用户 。
url_for()
用户数据保存后将转到登录页面 。 url_for() 根据登录视图的名称生成相应的 URL 。与写固定的 URL 相比 , 这样做的好处是如果以后需要修改该视图相应的 URL ,那么不用修改所有涉及到 URL 的代码。redirect() 为生成的 URL 生成一个重定向响应 。
flash()
如果验证失败 ,那么会向用户显示一个出错信息 。 flash() 用于储存在渲染模块时可以调用的信息。render_template()
当用户最初访问 auth/register 时,或者注册出错时 ,应用显示一个注册表单 。 render_template() 会渲染一个包含 HTML 的模板 。你会在教程的下一节 学习如何写这个模板 。4.2 实现登陆(login)视图
这个视图实现逻辑与前面register视图基本一致
flaskr/auth.py
@bp.route(/login, methods=(GET, POST)) def login(): # POST访问方式 ,进入表单与数据库的注册后台逻辑 if request.method == POST: username = request.form[username] password = request.form[password] db = get_db() error = None user = db.execute( "SELECT * FROM user WHERE username= ?", (username,) ).fetchone() # 后端验证用户是否能查询到,密码hash值是否能比对上 if user is None: error = 用户或密码错误! elif not check_password_hash(user[password], password): error = 用户或密码错误! # 通过验证后 ,设置cookie, 并跳转至首页 if error is None: session.clear() session[user_id] = user[id] return redirect(url_for(index)) # 页面闪现错误提示 flash(error) # GET访问方式 ,直接返回登陆页面 return render_template(auth/login.html)不同之处如下:
首先需要查询用户并存放在变量中 ,以备后用 。
fetchone() 根据查询返回一个记录行 。
如果查询没有结果 ,则返回 None 。后面还用到 fetchall() ,它返回包括所有结果的列表 。check_password_hash()
安全的比较哈希值 。如果匹配成功 ,那么密码就是正确的 。session 是一个 dict
它用于储存横跨请求的值 。当验证成功后 ,用户的 id 被储存于一个新的会话中 。会话数据被储存到一个 向浏览器发送的 cookie 中 ,在后继请求中 ,浏览器会返回它 。 Flask 会安全的对数据进行签名以防数据被篡改。现在用户的 id 已被储存在 session 中 ,可以被后续的请求使用 。 每个请求的开头 ,如果用户已登录 ,其他视图可读取这个session 。
4.3 验证session视图
@bp.before_app_request def load_logged_in_user(): user_id = session.get(user_id) if user_id is None: g.user = None else: g.user = get_db().execute( SELECT * FROM user where id = ?, (user_id,) ).fetchone() bp.before_app_request()
注册一个在视图函数之前运行的函数,不论其 URL 是什么。 load_logged_in_user 都会检查用户 id 是否已经储存在 session 中 ,并从数据库中获取用户数据 ,然后储存在 g.user 中 。 g.user
g.user的持续时间比请求要长 。 如果没有用户 id ,或者 id 不存在 ,那么 g.user 将会是 None 。4.4 注销视图(logout)
注销的时候需要把用户 id 从 session 中移除 。 然后 load_logged_in_user 就不会在后继请求中载入用户了 。
@bp.route(/logout) def logout(): session.clear() return redirect(url_for(index))4.5 判断已登录的装饰器(login_required)
用户登录以后才能创建 、编辑和删除博客帖子 。在每个视图中可以使用 下面装饰器来完成这个工作 。
def login_required(view): @functools.wraps(view) def wrapped_view(**kwargs): if g.user is None: return redirect(url_for(auth.login)) return view(**kwargs) returnwrapped_view url_for()
视图相关联的名称亦称为 端点 ,该函数自动跳转至该端点对应的url
一般情况:端点名称与视图函数名称相同 。如login视图函数名 ,则url_for(login)
蓝图情况:当使用蓝图的时候 ,蓝图的名称会添加到函数名称的前面 。上面的 login 函数是定义在蓝图auth中 , 所以他的端点为 auth.login 。装饰器函数看不懂的话 ,需要看下python 装饰器的相关文档 ,来了解装饰器函数的写法 。
5.其他
下篇文章会介绍模板 ,所以本章并未写相关html(register.html 、login.html)
另 ,因为本章不方便直接测试 ,待下章完成模板介绍后 ,会一起进行测试 。 联动调试模板和视图函数。如果你看到这里 ,真的感谢你的阅读 。写下一些学习的小tips:
如果你对文章代码依然懵懵懂懂,不要纠结 ,请看文章开头的官方文档链接 。大量的阅读各种官方文档 ,是一切的基础。 在大量看文档的同时,多敲代码 ,多次反复敲代码 ,敲完再搜索看文档查找不懂得地方 ,看似缓慢 ,其实你应不知不觉中超过绝大部分初学者了 。
3.学代码难点就在上面这两点 。 坚持完成上述1和2两个基础工作 ,你再看相关小项目和新的知识点就会容易理解并能很快实现了 。此时写些小项目 ,你会觉得非常简单 。看文档<---->对照敲样例代码<----->不理解的地方百度找答案----->自己动手写项目(或者报培训班快速积累开发经验)不要遗漏或跳过任何环节 ,循环反复 ,仅此而已 。
如果仅是为了找工作直接报名培训班 ,工作后又没有自学巩固补全之前的流程 ,大概率会沦为码农 。我们要做开发工程师可不是码农哦 。创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!