Python Flask框架-开发简单博客-认证蓝图
Posted Eason_LYC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Flask框架-开发简单博客-认证蓝图相关的知识,希望对你有一定的参考价值。
作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)
本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。基础薄弱的同学请戳Flask官方文档教程
本人经验,学习一门语言或框架时,
请首先阅读官方文档
。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。
如果Python都完全不熟悉,一定不要着急学习框架,
请首先学习python官方文档,一步一个脚印。要不然从入门到放弃是大概率事件。
Python 官方文档教程
本系列已发布文章:
文章目录
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)
return wrapped_view
url_for()
视图相关联的名称亦称为端点
,该函数自动跳转至该端点对应的url
一般情况:端点名称与视图函数名称相同。如login视图函数名,则url_for('login')
蓝图情况:当使用蓝图的时候,蓝图的名称会添加到函数名称的前面。上面的 login 函数是定义在蓝图auth中, 所以他的端点为auth.login
。
装饰器函数看不懂的话,需要看下python 装饰器的相关文档,来了解装饰器函数的写法。
5.其他
下篇文章会介绍模板,所以本章并未写相关html(register.html、login.html)
另,因为本章不方便直接测试,待下章完成模板介绍后,会一起进行测试。 联动调试模板和视图函数。
如果你看到这里,真的感谢你的阅读。写下一些学习的小tips:
- 如果你对文章代码依然懵懵懂懂,不要纠结,请看文章开头的官方文档链接。大量的阅读各种官方文档,是一切的基础。
- 在大量看文档的同时,多敲代码,多次反复敲代码,敲完再搜索看文档查找不懂得地方,看似缓慢,其实你应不知不觉中超过绝大部分初学者了。
3.学代码难点就在上面这两点。 坚持完成上述1和2两个基础工作,你再看相关小项目和新的知识点就会容易理解并能很快实现了。此时写些小项目,你会觉得非常简单。
看文档<---->对照敲样例代码<----->不理解的地方百度找答案----->自己动手写项目(或者报培训班快速积累开发经验)
不要遗漏或跳过任何环节,循环反复,仅此而已。
如果仅是为了找工作直接报名培训班,工作后又没有自学巩固补全之前的流程,大概率会沦为码农。我们要做开发工程师可不是码农哦。
Python Flask框架-开发简单博客-开篇介绍
作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他拥有的,而不是他会的。所以可以不学无数,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
我们追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)
本专栏是对flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。基础薄弱的同学请戳Flask官方文档教程
文章目录
1. 什么是Flask
1.1 核心理念
Flask框架是Python中的一个非常重要的WEB开发框架
,与另一个重量级Python Web框架Django齐名。但与Django的重和全不同,Flask强调灵活
和简单
。所以我们也会称Flask为微框架
。
微框架中的“微”字表示 Flask 的目标是保持核心简单而又可扩展
。 Flask 不会替你做出许多决定,比如选用何种数据库、使用何种模板引擎,在flask中这些都是非常容易改变的。Flask可以变成你任何想要的东西,一切恰到好处,由你做主。
缺省配置情况下, Flask 不包含数据库抽象层、表单验证或者其他已经有成熟第三方扩展能实现的功能。Flask的理念是通过使用这些扩展为应用添加所需功能,就如同这些功能是 Flask 原生的一样。大量的扩展用以支持数据库整合、表单验证、上传处理和各种开放验证等等。 Flask 可能是“微小”的,但它已经为满足您的各种生产需要做出了充足的准备。
一旦你开始使用 Flask ,你会发现有各种各样的扩展可供使用。 Flask 作为一个非常简约而优秀的胶合层
,就像 Python 语言一样。
1.2 一个最小的应用
- 首先,安装flask框架
pip install Flask
- 其次,启动flask,一个应用就此诞生
# hello.py
"""
1. 首先我们导入Flask类。
2. 接着我们创建一个该类的实例:app。第一个参数是应用模块或者包的名称。 __name__ 可以简单认为代表目前这个文件。有了这个参数Flask会读取参数所提供的文件的内容,来获取app模板或是静态文件。
3. 然后我们使用 route() 装饰器来告诉 Flask 触发函数的URL。
4. 函数返回需要在用户浏览器中显示的信息。默认的内容类型是 HTML ,因此字符串中的HTML会被浏览器渲染
"""
from flask import Flask # 1
app = Flask(__name__) # 2
@app.route("/") # 3
def hello_world():
return "<p>Hello, World!</p>" # 4
- 最后,启动。这个需要临时设置一个环境变量
CMD使用命令
> set FLASK_APP=hello
> flask run
Powershell使用命令
> $env:FLASK_APP = "hello"
> flask run
Bash使用命令
$ export FLASK_APP=hello
$ flask run
在后续的文章中,我会介绍一种简单的pycharm配置,做到一键启动。
2. 个人博客要实现的功能点和效果展示
2.1 功能点
非常简单的个人博客,但是通过实现这些功能,可以快速对Flask框架有个直接的认识,并能为后续深入自学提供一个非常好的入手点。
2.2 Blog效果展示
2.2.1 登陆、注册页面
2.2.2 首页(非登录用户\\登陆用户),注意右侧有区别
2.2.3 登陆用户的文章新建(New)\\文章编辑功能(Edit)
页面过于简单了,仅为了减少其他知识点的干扰,专注于flask的学习而已。
3. 实现大纲(知识点)
这个思维导图会在后续文章中不断完善,直至本专栏所有文章结束,形成完整的思维导图。这个形成过程,就是我从Flask官方文档中总结归纳的所有知识点。
以上是关于Python Flask框架-开发简单博客-认证蓝图的主要内容,如果未能解决你的问题,请参考以下文章