企业管理系统定制开发Python Flask框架-开发简单博客-认证蓝图

作者:Eason_LYC
企业管理系统定制开发悲观者预言失败,十言九中。 企业管理系统定制开发乐观者创造奇迹,一次即可。
企业管理系统定制开发一个人的价值,企业管理系统定制开发在于他所拥有的。企业管理系统定制开发可以不学无术,企业管理系统定制开发但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。企业管理系统定制开发我的专栏文章知识点全面细致,逻辑清晰、结合实战,企业管理系统定制开发让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
企业管理系统定制开发追求技术至上,企业管理系统定制开发这是我们理想中的极乐世界~(企业管理系统定制开发关注我即可加入社区)

企业管理系统定制开发本专栏是对Flask官方文档中个人博客搭建进行的归纳总结,与官方文档结合事半功倍。基础薄弱的同学请戳

本人经验,学习一门语言或框架时,请首先阅读官方文档。学习完毕后,再看其他相关文章(如本系列文章),才是正确的学习道路。

如果Python都完全不熟悉,一定不要着急学习框架,请首先学习python官方文档,一步一个脚印。要不然从入门到放弃是大概率事件。

本系列已发布文章:

文章目录

1. 本章知识点总结

2. 蓝图功能分析

框架中蓝图注册分为两步,第一步新建蓝图模块,第二步在工厂函数中注册蓝图。

auth.py的作用: auth蓝图部分的视图代码实现
auth模块用于认证相关工作,访问路径问 “/auth/函数名”。主要功能包括:注册、登陆、验证session、注销、判断已登录的装饰器

  1. 注册:用户点击注册,输入拟注册的用户名和密码,前后端均验证。通过后跳转至登陆页面。
  2. 登陆:用户点击登录,输入用户名和密码,前后端均验证。通过后完成登陆,生成并保存session。以登录用户的身份浏览博客;
  3. 验证session:用户登录首页,先判断是否有session,若有则从数据库提取对应用户信息,以登录用户的身份浏览博客;
  4. 注销:用户点击注销,删除session,退出登陆状态。
  5. 判断已登录的装饰器:各页面对是否登录的浏览者展现内容略有不同,通过此装饰器实现后台的自动判断,区别响应登陆或未登录的浏览者

代码所需库

仅是为了后续查找学习方便,在此处列出。实际代码开发中,是在写代码时,需要用到哪个库,逐步添加即可。

flaskr/auth.py

import functoolsfrom flask import Blueprint, request, render_template, flash, session, redirect, url_for, gfrom werkzeug.security import generate_password_hash, check_password_hashfrom flaskr.db import get_db
  • 1
  • 2
  • 3
  • 4

文件结构

3. 蓝图创建和注册

在flaskr文件夹下新建auth.py,创建一个名称为 ‘auth’ 的 Blueprint 。和应用对象一样, 蓝图需要知道是在哪里定义的,因此把 name 作为函数的第二个参数。 url_prefix 会添加到所有与该蓝图关联的 URL 前面。

flaskr/auth.py

# 1. 注册蓝图bp = Blueprint('auth', __name__, url_prefix='/auth')
  • 1
  • 2

使用 app.register_blueprint() 导入并注册 蓝图。

flaskr/init.py

def create_app():    app = ... # 之前的代码   # 本次新增的代码,蓝图注册    from . import auth    app.register_blueprint(auth.bp)    return app # 之前的代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  1. @bp.route 作用
    关联了 URL /register 和 register 视图函数。当 Flask 收到一个指向 /auth/register 的请求时就会调用 register 视图并把其返回值作为响应。

  2. request.form
    是一个特殊类型的 dict ,其映射了提交表单的键和值。表单中,用户将会输入其 username 和 password 。

  3. 验证 username 和 password 不为空。如果验证成功,就把新用户的数据插入数据库。

  4. db.execute
    使用了带有 ? 占位符的 SQL 查询语句。
    占位符可以代替后面的元组参数中相应的值。使用占位符的好处是会自动帮你转义输入值 ,以抵御 SQL 注入攻击 。

  5. generate_password_hash()
    因为安全原因,不能把密码明文储存在数据库中。而是应当使用 generate_password_hash() 生成安全的哈希值, 再把哈希值储存到数据库中。因为查询修改了数据,所以要使用 db.commit() 保存修改。

  6. 如果用户名已存在,会产生一个 sqlite3.IntegrityError 错误, 应当将该错误作为一个验证错误显示给用户。

  7. url_for()
    用户数据保存后将转到登录页面。 url_for() 根据登录视图的名称生成相应的 URL 。与写固定的 URL 相比, 这样做的好处是如果以后需要修改该视图相应的 URL ,那么不用修改所有涉及到 URL 的代码。

  8. redirect() 为生成的 URL 生成一个重定向响应。

  9. flash()
    如果验证失败,那么会向用户显示一个出错信息。 flash() 用于储存在渲染模块时可以调用的信息。

  10. 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')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

不同之处如下:

  1. 首先需要查询用户并存放在变量中,以备后用。

  2. fetchone() 根据查询返回一个记录行。
    如果查询没有结果,则返回 None 。后面还用到 fetchall() ,它返回包括所有结果的列表。

  3. check_password_hash()
    安全的比较哈希值。如果匹配成功,那么密码就是正确的。

  4. session 是一个 dict
    它用于储存横跨请求的值。当验证成功后,用户的 id 被储存于一个新的会话中。会话数据被储存到一个 向浏览器发送的 cookie 中,在后继请求中,浏览器会返回它。 Flask 会安全的对数据进行签名以防数据被篡改。

  5. 现在用户的 id 已被储存在 session 中,可以被后续的请求使用。 每个请求的开头,如果用户已登录,其他视图可读取这个session。

4.3 验证session视图

@bp.before_app_requestdef 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. bp.before_app_request()
    注册一个在视图函数之前运行的函数,不论其 URL 是什么。 load_logged_in_user 都会检查用户 id 是否已经储存在 session 中,并从数据库中获取用户数据,然后储存在 g.user 中。
  2. 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'))
  • 1
  • 2
  • 3
  • 4

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. url_for()
    视图相关联的名称亦称为 端点 ,该函数自动跳转至该端点对应的url
    一般情况:端点名称与视图函数名称相同。如login视图函数名,则url_for('login')
    蓝图情况:当使用蓝图的时候,蓝图的名称会添加到函数名称的前面。上面的 login 函数是定义在蓝图auth中, 所以他的端点为 auth.login

装饰器函数看不懂的话,需要看下python 装饰器的相关文档,来了解装饰器函数的写法。

5.其他

下篇文章会介绍模板,所以本章并未写相关html(register.html、login.html)
另,因为本章不方便直接测试,待下章完成模板介绍后,会一起进行测试。 联动调试模板和视图函数。

如果你看到这里,真的感谢你的阅读。写下一些学习的小tips:

  1. 如果你对文章代码依然懵懵懂懂,不要纠结,请看文章开头的官方文档链接。大量的阅读各种官方文档,是一切的基础。
  2. 在大量看文档的同时,多敲代码,多次反复敲代码,敲完再搜索看文档查找不懂得地方,看似缓慢,其实你应不知不觉中超过绝大部分初学者了。
    3.学代码难点就在上面这两点。 坚持完成上述1和2两个基础工作,你再看相关小项目和新的知识点就会容易理解并能很快实现了。此时写些小项目,你会觉得非常简单。

看文档<---->对照敲样例代码<----->不理解的地方百度找答案----->自己动手写项目(或者报培训班快速积累开发经验)不要遗漏或跳过任何环节,循环反复,仅此而已。
如果仅是为了找工作直接报名培训班,工作后又没有自学巩固补全之前的流程,大概率会沦为码农。我们要做开发工程师可不是码农哦。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发