使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(三)——使用Flask-Login库实现登录功能
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(四)——对 run.py 的调整
使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能
为了熟悉 Python 的 Web 开发,找到这个框架。在这里记录下使用它来写一个简单的登录 Demo 功能过程中碰到的问题。
上面几个链接就是使用到相关的库的文档。
Flask_Login 这个是官方实现的一套登录验证的库。
Flask_sqlalchemy 是官方对 sqlalchemy 库的一个封装,它是一个ORM,用于做数据库访问。
这里使用的开发工具是 PyCharm,使用这个工具可以直接创建一个 Flask 的项目。
一、从一个简单的示例说起
创建一个 run.py 的代码文件存放在项目的根目录下。
run.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()
这是官方文档上的一个最简单能直接运行的应用了
这里要注意的有两个地方:
1.@app.route('/')
这里定义的是一个完整的路由,也就是说,现在这里定义的是“/”,则真实访问的地址就是首页。
2.app 对象
在该对象中进行的一切操作都是全局有效的。
示例:我要在所有的请求开始前,进行一些初始化操作,就可以这样直接使用 app 对象来定义
@app.before_request def before_request(): pass
完整的代码是:
from flask import Flask app = Flask(__name__) @app.before_request def before_request(): pass if __name__ == '__main__': app.run()
二、创建应用
根据官方文档的说明,大型应用的目录结构是:
/yourapplication /runserver.py /yourapplication /__init__.py /views.py /static /style.css /templates layout.html index.html login.html ...
所以,要在项目的根目录下,创建一个应用的目录,这里则创建一个 demo 的应用,同时,将根目录下的 static 和 templates 文件夹删除。
在 demo 目录下,创建 3 个文件,分别是:“__init__.py”,“config.py”,“requirements.txt”。
__init__.py 这个就不多说了。
config.py 这个是 Flask 的配置信息。
requirements.txt 这个是用于方便 python 导入库使用的。
requirements.txt 文件里加上以下,这些都是要使用到的库。
Flask Flask-SQLAlchemy Flask-Login Flask-WTF pygments PyMySQL
三、封装 SQLAlchemy 库
1.在 config.py 文件增加以下配置
DEBUG = True SQLALCHEMY_ECHO = False SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:root@localhost/test?charset=utf8' SECRET_KEY = '*\xff\x93\xc8w\x13\x0e@3\xd6\x82\x0f\x84\x18\xe7\xd9\\|\x04e\xb9(\xfd\xc3'
2.在 demo 目录下创建一个 common 目录,做为公共库,在该目录下创建 data.py 文件
使用 fetchall() 是取得 SQL 脚本的返回结果,rowcount 才是取得影响行数。
# config=utf-8 from sqlalchemy import create_engine from sqlalchemy.sql import text from demo.config import SQLALCHEMY_DATABASE_URI, SQLALCHEMY_ECHO def db_query(sql, settings=None, echo=None, args=None): """ 执行增删改 SQL 语句 Args: sql: SQL 语句 settings: 数据库连接字符串 echo: 是否输出 SQL 语句 args: SQL 参数 Returns: 执行结果 """ if settings is None: settings = SQLALCHEMY_DATABASE_URI if echo is None: echo = SQLALCHEMY_ECHO return create_engine(settings, echo=echo).connect().execute(text(sql), args).fetchall() def db_execute(sql, settings=None, echo=None, args=None): """ 执行增删改 SQL 语句 Args: sql: SQL 语句 settings: 数据库连接字符串 echo: 是否输出 SQL 语句 args: SQL 参数 Returns: 影响行数 """ if settings is None: settings = SQLALCHEMY_DATABASE_URI if echo is None: echo = SQLALCHEMY_ECHO return create_engine(settings, echo=echo).connect().execute(text(sql), args).rowcount # 测试代码 # SELECT * FROM py_user # INSERT INTO py_user(name) VALUES('123456') # data = db_query("SELECT * FROM py_user") # print(data) # data = db_execute("INSERT INTO py_user(name) VALUES(:name)", args={'name': '123456'}) # print(data)
3. 在 common 目录下创建一个 __init__.py 文件
__init__.py:
# config=utf-8 from flask_sqlalchemy import SQLAlchemy __all__ = ['db'] db = SQLAlchemy()
这代码用于注册这个数据访问库。
四、初始化应用
对 app 要进行数据库注册,还有传入配置信息等,要注意的是,这里需要另开一个文件来做这些事,不可以全写在 run.py 文件里,因为以后会在使用其它库的时候,在这里进行注册,但在真实使用时就要调用这里生成的对象,这个时候两个文件相互 import 就会出现异常。
所以,这里将 run.py 中创建 app 对象的功能提取到 demo 目录下的 __init__.py 文件里。
/demo/__init__.py
# config=utf-8 from flask import Flask from demo.common import db def create_app(config_filename=None): app = Flask(__name__) if config_filename is not None: # 注册数据访问信息 app.config.from_pyfile(config_filename) # 初始化数据库 configure_database(app) return app def configure_database(app): """初始化数据库连接。 Args: app:应用对象。 Returns: 该函数没有返回值。 """ db.init_app(app)
/run.py 文件里的代码则修改成
# config=utf-8 from flask import g from flask_login import current_user from demo import create_app app = create_app('config.py') @app.before_request def before_request(): """ 这里是全局的方法,在请求开始之前调用。 其中 flask 有个全局的变量 g,它是和 session 一样的用途,可以使用它来保存当前用户的数据 Returns: """ g.user = current_user pass if __name__ == '__main__': app.run()