当前位置: 首页 > wzjs >正文

网站域名注册要多少钱室内设计培训班学费一般多少

网站域名注册要多少钱,室内设计培训班学费一般多少,成都网站建设公司排行,在线制作图片加字合成八、上下文管理 在 Flask 框架中,上下文管理是一项关键特性,它允许开发者在应用程序的不同部分之间共享数据,并且确保在请求处理期间相关的资源(如数据库连接)能够正确地初始化和清理。Flask 中有两种主要的上下文类型…

八、上下文管理

在 Flask 框架中,上下文管理是一项关键特性,它允许开发者在应用程序的不同部分之间共享数据,并且确保在请求处理期间相关的资源(如数据库连接)能够正确地初始化和清理。Flask 中有两种主要的上下文类型:应用上下文(app context)和请求上下文(request context)。

8.1 请求上下文

在 Flask 中,请求上下文是一个关键概念,它包含了处理请求所需的所有信息。当 Flask 接收到一个 HTTP 请求时,会创建一个请求上下文,这个上下文会一直存在,直到请求处理完成。请求上下文的存在使得在整个请求处理过程中,不同的函数和模块都能方便地访问与该请求相关的数据。它有两个核心对象request 对象、session 对象,前边已经介绍了request对象,这里重点介绍下session对象。

1.session对象

session对象是flask.sessions.Session类的实例,用于在不同请求之间存储特定于用户会话的数据。这对于维护用户状态,如用户登录状态、购物车内容等功能至关重要。

session 对象本质上是一个字典,Flask 使用加密的Cookie在客户端和服务器之间传递 session 数据。当客户端发起请求时,Flask 检查请求中的 session Cookie。如果 Cookie存在且签名验证通过,Flask 会将Cookie中的数据加载到 session 对象中,这样在视图函数中就可以访问和修改这些数据。当请求结束时,session 对象中的任何更改都会被序列化并存储回 session Cookie,发送给客户端。

在使用 session 之前,需要设置一个 SECRET_KEY。这个密钥用于对 session Cookie 进行加密和签名,确保数据的安全性。可以在 Flask 应用初始化时设置:

from flask import Flask, sessionapp = Flask(__name__)
app.secret_key = 'your_secret_key'

请务必将 'your_secret_key' 替换为一个强密钥。在生产环境中,建议从环境变量或配置文件中读取密钥,而不是硬编码。

from flask import Flask, session, request, redirect, url_forapp = Flask(__name__)
app.secret_key = 'your_secret_key'@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form.get('username')# 设置会话变量,将用户名存储在session中session['username'] = usernamereturn redirect(url_for('profile'))return '''<form method="post"><label for="username">用户名:</label><input type="text" id="username" name="username" required><input type="submit" value="登录"></form>'''@app.route('/profile')
def profile():# 从session中获取用户名username = session.get('username')if username:return f'欢迎,{username}!这是你的个人资料页面。'return redirect(url_for('login'))if __name__ == '__main__':app.run(debug=True)

2. 请求上下文的生命周期

  • 创建:当 Flask 应用接收到一个 HTTP 请求时,会自动创建请求上下文。请求上下文被压入一个栈(_request_ctx_stack)中,这个栈确保每个线程都有自己独立的上下文栈,保证多线程环境下请求处理的隔离性。

  • 使用:在请求处理过程中,例如在视图函数、中间件等地方,都可以通过requestsession对象访问请求上下文的信息。

  • 销毁:一旦请求处理完成,无论是正常结束还是发生异常,请求上下文都会从栈中弹出并销毁。这意味着requestsession对象中的数据在请求处理完成后将不再可用,除非将相关数据保存到其他地方(如数据库)。

    from flask import Flask, session, request, redirect, url_forapp = Flask(__name__)
    app.secret_key = 'your_secret_key'# 创建
    @app.route('/login', methods=['GET', 'POST'])
    def login():if request.method == 'POST':username = request.form.get('username')session['username'] = usernamereturn redirect(url_for('profile'))return '''<form method="post"><label for="username">用户名:</label><input type="text" id="username" name="username" required><input type="submit" value="登录"></form>'''# 使用
    @app.route('/profile')
    def profile():username = session.get('username')if username:return f'欢迎,{username}!这是你的个人资料页面。'return redirect(url_for('login'))# 销毁
    @app.route('/logout')
    def logout():# 从session中移除用户名session.pop('username', None)return redirect(url_for('login'))if __name__ == '__main__':app.run(debug=True)
    

3. 手动操作请求上下文

​ 在某些情况下,例如单元测试或者需要模拟请求的场景中,可能需要手动操作请求上下文。可以使用with语句结合app.test_request_context()来手动创建请求上下文。例如:

from flask import Flask, requestapp = Flask(__name__)@app.route('/')
def index():return f"请求路径: {request.path}"with app.test_request_context('/test_path'):result = index()print(result)
  • 在上述代码中,app.test_request_context('/test_path')创建了一个模拟的请求上下文,路径为/test_path。在这个上下文环境中调用index函数,就好像 Flask 真正接收到了一个指向/test_path的请求一样。

8.2 应用上下文

在 Flask 中,应用上下文(Application Context)是一个重要的概念,它管理着与 Flask 应用实例相关的数据和状态。与请求上下文主要处理单个请求不同,应用上下文的作用域更侧重于整个应用程序,并且在应用的生命周期内可能会被多次激活和使用。

1. 应用上下文的作用

  • 存储应用级数据:应用上下文提供了一个地方来存储与应用相关的全局数据,这些数据在整个应用的不同部分都可以访问。例如,可以在应用上下文中存储数据库连接池、配置对象等,这样在不同的视图函数、扩展或其他应用组件中都能方便地获取这些资源,而无需在每个地方重复创建或配置。
  • 关联应用实例:它将当前的执行环境与特定的 Flask 应用实例相关联。在多应用(如在一个进程中运行多个 Flask 应用实例)或者在使用 Flask 扩展的情况下,应用上下文确保每个操作都与正确的应用实例相关联,避免混淆和错误。

2. 应用上下文对象

​ Flask 的应用上下文主要由两个对象组成:

  • current_app:指向当前激活的 Flask 应用实例。通过这个对象,你可以访问应用的各种配置、属性和方法。例如,current_app.config 可以获取应用的配置信息,current_app.logger 可以使用应用的日志记录器。
  • g:这是一个全局对象,用于在请求处理过程中临时存储数据。与 current_app 不同,g 的数据只在当前请求处理期间有效,且每个请求都有自己独立的 g 对象。不过,由于应用上下文在请求处理期间也是激活的,所以可以在请求处理过程中通过 g 来传递一些与当前请求相关,但又可能在不同函数间共享的数据。

3. 应用上下文的激活与销毁

  • 自动激活:在处理请求时,Flask 会自动激活应用上下文和请求上下文。当一个请求进入应用,Flask 首先会激活应用上下文,然后再激活请求上下文。这确保了在请求处理过程中,应用级别的数据和当前请求相关的数据都可以被正确访问。
  • 手动激活:在某些情况下,比如在自定义的命令行脚本或者扩展中,可能需要手动激活应用上下文。可以使用 app.app_context() 方法来手动创建并激活应用上下文。例如:
from flask import Flaskapp = Flask(__name__)with app.app_context():# 在这个代码块内,应用上下文被激活print(current_app.config['SECRET_KEY'])

在上述代码中,with app.app_context() 语句创建了一个应用上下文,并在 with 代码块内保持激活状态。在这个代码块中,可以使用 current_app 访问应用的配置信息。

  • 销毁:当请求处理完成或者手动创建的应用上下文代码块结束时,应用上下文会被销毁。在销毁过程中,Flask 会自动清理与该应用上下文相关的资源,确保不会出现资源泄漏。

4. 应用上下文的使用场景

  • 数据库连接管理:在应用启动时,可以在应用上下文中初始化数据库连接池,并在整个应用的生命周期内复用这些连接。不同的视图函数在处理请求时,可以从应用上下文中获取数据库连接,而无需每次都重新建立连接,提高了应用的性能和资源利用率。例如:
import sqlite3
from flask import Flask, gapp = Flask(__name__)def get_db():if 'db' not in g:g.db = sqlite3.connect('example.db')return g.db@app.teardown_appcontext
def close_db(error):db = g.pop('db', None)if db is not None:db.close()@app.route('/')
def index():db = get_db()# 使用数据库连接执行查询等操作return 'Hello, World!'

在上述代码中,get_db 函数在应用上下文中获取数据库连接,如果连接不存在则创建一个。@app.teardown_appcontext 装饰的 close_db 函数在应用上下文销毁时关闭数据库连接。此代码并不能直接运行,仅是一个示例,详细的数据库连接请看后面第九章数据库集成

  • 配置管理:应用上下文可以方便地访问应用的配置信息。例如,在视图函数或者扩展中,可以通过 current_app.config 获取配置参数,根据不同的配置执行不同的逻辑。
from flask import Flask, current_appapp = Flask(__name__)
app.config['DEBUG_MODE'] = True@app.route('/')
def index():if current_app.config['DEBUG_MODE']:return '应用处于调试模式'return '应用处于生产模式'

理解和正确使用应用上下文对于构建健壮、高效的 Flask 应用至关重要,它提供了一种有效的方式来管理应用级别的资源和数据,并确保这些资源在整个应用生命周期内的正确使用和清理。

九、会话管理

在 Web 应用开发中,会话管理是一项关键功能,它允许 Web 应用在多个请求之间跟踪用户状态和数据。在 Flask 框架里,会话管理通过 session 对象实现,该对象基于客户端的 Cookie 机制,提供了一种安全且便捷的方式来存储和访问用户特定的数据。

9.1 启用会话

Flask 中的会话默认是基于客户端的 Cookie 实现的。在应用中不需要额外的启用步骤,但需要设置一个密钥来对会话数据进行加密签名,以确保数据的安全性。

from flask import Flaskapp = Flask(__name__)
app.secret_key ='my_secret_key'  # 请使用更复杂和安全的密钥在实际应用中

9.2 存储和获取会话数据

可以像操作字典一样存储和获取会话数据。

@app.route('/set_session')
def set_session():session['username'] = 'John'session['logged_in'] = Truereturn 'Session data set'@app.route('/get_session')
def get_session():username = session.get('username')logged_in = session.get('logged_in', False)return f'Username: {username}, Logged In: {logged_in}'

9.3 删除会话数据

@app.route('/clear_session')
def clear_session():session.pop('username', None)session.pop('logged_in', None)return 'Session data cleared'

9.4 会话有效期

1. 默认会话有效期

在 Flask 中,默认情况下,会话基于客户端的Cookie实现。会话Cookie在用户关闭浏览器时会被删除,这意味着会话数据的有效期默认到浏览器关闭为止。这种会话类型被称为 “非持久会话”。

2. 设置持久会话

如果你希望会话在浏览器关闭后仍然有效,可以通过将会话标记为持久化来实现。在 Flask 中,可以在设置会话数据时,通过设置 session.permanent = True 来实现。

python
from flask import Flask, session, redirect, url_forapp = Flask(__name__)
app.secret_key ='my_secret_key'@app.route('/set_permanent_session')
def set_permanent_session():session.permanent = True # 将会话标记为持久化session['username'] = 'John'session['logged_in'] = Truereturn redirect(url_for('get_session'))@app.route('/get_session')
def get_session():username = session.get('username', 'Guest')logged_in = session.get('logged_in', False)return f'Username: {username}, Logged In: {logged_in}'if __name__ == '__main__':app.run(debug = True)

3. 设置会话有效期时间

对于持久化会话,你还可以设置其确切的有效期。Flask 应用有一个 PERMANENT_SESSION_LIFETIME 配置变量,用于指定持久化会话的有效期。它是一个 datetime.timedelta 对象。

from flask import Flask, session, redirect, url_for
from datetime import timedeltaapp = Flask(__name__)
app.secret_key ='my_secret_key'
# 设置持久化会话的有效期为 30 分钟或者设置day = 7,设置有效期为一周
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes = 30)@app.route('/set_permanent_session')
def set_permanent_session():session.permanent = Truesession['username'] = 'John'session['logged_in'] = Truereturn redirect(url_for('get_session'))# 重定向@app.route('/get_session')
def get_session():username = session.get('username', 'Guest')logged_in = session.get('logged_in', False)return f'Username: {username}, Logged In: {logged_in}'if __name__ == '__main__':app.run(debug = True)
  • 在这个示例中,通过 app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes = 30) 将持久化会话的有效期设置为 30 分钟。超过这个时间后,会话数据将失效。

  • 注意事项

    • 虽然持久化会话提供了更长的有效期,但由于会话数据存储在客户端 Cookie 中,不要在会话中存储敏感信息,如密码等。
  • 要确保 secret_key 的保密性和强度,因为它用于对会话数据进行加密签名,防止数据被篡改。如果 secret_key 泄露,攻击者可能会伪造或篡改会话数据。

9.5 安全性考量

  • SECRET_KEY 安全SECRET_KEY 必须足够复杂且保密,避免使用容易猜测的值。建议使用长且随机的字符串作为 SECRET_KEY

  • 数据验证:由于 session 数据存储在客户端,虽然经过签名验证,但仍不应存储敏感信息,如密码。在使用 session 数据时,始终要进行必要的验证和过滤,防止潜在的安全漏洞。

  • Cookie 安全设置:可以通过配置 Flask 应用来设置 session Cookie的一些安全属性,如 httponlysecurehttponly 确保 Cookie 不能通过 JavaScript 访问,减少 XSS 攻击获取 Cookie 的风险;secure 确保 Cookie 仅在 HTTPS 连接下发送,防止中间人攻击窃取 Cookie 数据。

    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_SECURE'] = True
    

通过合理利用 Flask 的会话管理功能,并遵循安全最佳实践,可以有效地跟踪用户状态,提供个性化的用户体验,同时保障应用的安全性。

十、数据库集成

Flask 是一个轻量级的 Web 框架,本身不具备数据持久化能力。通过集成数据库,可以将应用产生的数据(如用户注册信息、文章内容等)保存下来,以便后续使用。这里只简单介绍数据库的基本应用,包括数据库的连接、配置、模型类定义、简单的数据插入、查询、更新、删除等操作。数据库集成高级应用请关注后续更新。

10.1 安装必要的库

要在 Flask 中连接 MySQL 数据库,需要安装 flask_sqlalchemymysql-connector-python(用于连接 MySQL 数据库)。可以使用以下命令通过 pip 安装:

pip install flask_sqlalchemy 
pip install mysql-connector-python

10.2 配置数据库

1. 创建数据库并添加用户表

请参考以往文章,创建数据库test_db并创建表user_info,下边是SQL语句:

-- 创建数据库 test_db,如果数据库已存在则不执行创建操作
CREATE DATABASE IF NOT EXISTS test_db;-- 使用 test_db 数据库
USE test_db;-- 在 test_db 数据库中创建 user_info 表
CREATE TABLE user_info (user_id INT AUTO_INCREMENT PRIMARY KEY,user_name VARCHAR(50) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(100) UNIQUE NOT NULL,phone_number VARCHAR(20),creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 数据库URL配置

使用 app.config['SQLALCHEMY_DATABASE_URI'] 配置数据库连接字符串。对于 MySQL 数据库,格式为 mysql+mysqlconnector://username:password@localhost:post/dbname,其中包含数据库类型(mysql)、驱动(mysqlconnector)、用户名(username)、密码(password)、主机地址(localhost)、端口号(post)和数据库名(dbname)等信息。

# 请将username、password、post(端口号)、数据库名更换为你的配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://username:password@localhost:3306/test_db'

注意:请勿在配置字符串中添加空格。

3. 其它关于数据库的配置

  1. 数据库连接URI配置

    • MySQLapp.config['SQLALCHEMY_DATABASE_URI'] ='mysql+mysqlconnector://username:password@localhost:3306/test_db'
    • PostgreSQLapp.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://username:password@localhost:5432/test_db'
    • SQLiteapp.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'(文件型数据库,test.db是数据库文件名,若不存在则会自动创建;如果使用内存数据库,可写成sqlite://
  2. 跟踪修改配置

    • app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False:默认值为True,Flask - SQLAlchemy 会跟踪对象的修改并发送信号。这在调试和某些特定场景下可能有用,但会增加内存开销。一般在生产环境中建议设置为False
  3. 连接池相关配置

    • app.config['SQLALCHEMY_POOL_SIZE'] = 10:设置数据库连接池的大小,即连接池中保持的数据库连接数量。此处表示连接池大小为 10 个连接。
    • app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20:设置连接池最大溢出连接数。当连接池已满时,若还有连接请求,SQLAlchemy 会额外创建最多SQLALCHEMY_MAX_OVERFLOW个连接。此处表示连接池可以额外溢出 20 个连接。
    • app.config['SQLALCHEMY_POOL_TIMEOUT'] = 30:设置从连接池中获取连接的超时时间(秒)。如果在这个时间内无法获取到连接,会抛出异常。此处表示获取连接的超时时间为 30 秒。
  4. 连接池回收时间配置

    • app.config['SQLALCHEMY_POOL_RECYCLE'] = 3600 :设置连接在连接池中的最长存活时间(秒)。超过这个时间,连接会被回收并重新创建,以防止数据库服务端关闭空闲连接导致的连接失效问题。此处表示连接在连接池中最长存活 1 小时。
  5. 引擎选项配置

    SQLALCHEMY_ENGINE_OPTIONS配置项允许你向 SQLAlchemy 的数据库引擎传递额外的选项。这些选项高度依赖于所使用的数据库类型,不同数据库支持的选项有所不同。

    • MySQL

      app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'connect_args': {'connect_timeout': 10,'charset': 'utf8mb4'},'poolclass': QueuePool,'pool_size': 5,'pool_reset_on_return': 'rollback','echo_pool': True
      }
      
      • connect_args :中设置了连接超时时间为 10 秒和字符集为 utf8mb4
      • poolclass: 使用默认的 QueuePool 连接池。
      • pool_size :设置连接池大小为5
      • pool_reset_on_return: 设置连接返回连接池时回滚事务。
      • echo_pool: 开启连接池活动日志记录。
    • PostgreSQL

      app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'strategy': 'threadlocal','connect_args': {'application_name': 'MyFlaskApp','sslmode':'require'},'execution_options': {'autocommit': False}
      }
      
      • strategy :设置为 threadlocal,为每个线程维护独立连接。
      • connect_args:中设置了应用程序名称为 MyFlaskApp 且要求使用 SSL 连接。
      • execution_options:将 autocommit 设置为 False,意味着需要手动管理事务。
    • SQLite

      app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'connect_args': {'isolation_level': None,'detect_types': sqlite3.PARSE_DECLTYPES},'poolclass': QueuePool,'pool_size': 2,'echo_pool': False
      }
      
  6. 数据库会话相关

    • app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True:如果设置为 True,Flask - SQLAlchemy 会在每次请求结束时自动提交数据库会话中的更改。这意味着在请求处理过程中对数据库所做的所有修改,在请求结束时会自动提交到数据库持久化保存。如果设置为 False(默认值),则需要手动调用 db.session.commit() 来提交更改。
    • **注意事项:**虽然自动提交在某些场景下很方便,但在复杂的事务处理或需要精细控制数据库操作的情况下,手动提交更有助于保证数据的一致性和事务的完整性。
  7. 日志相关

    • app.config['SQLALCHEMY_ECHO'] = True:当设置为 True 时,SQLAlchemy 会将所有生成的 SQL 语句输出到标准输出(通常是控制台)。这在开发和调试过程中非常有用,能够帮助开发者查看实际执行的 SQL 语句,方便排查数据库相关的问题,比如查询语句是否正确、参数是否正确传递等。
    • **注意事项:**在生产环境中,由于性能和安全原因(可能会暴露敏感信息,如数据库用户名和密码在某些复杂查询日志中),一般不建议开启此选项。
  8. 元数据缓存相关

    • 用于配置多个数据库连接(绑定)。如果你的应用需要连接多个不同的数据库(例如,一个主数据库用于主要业务数据,另一个数据库用于日志记录等),可以使用此配置。它是一个字典,键是绑定名称,值是对应的数据库连接 URI。

      app.config['SQLALCHEMY_BINDS'] = {'secondary_db':'sqlite:///secondary.db',
      }
      

      在模型定义时,可以通过 __bind_key__ 属性指定使用哪个绑定的数据库:

      class SecondaryModel(db.Model):__bind_key__ ='secondary_db'id = db.Column(db.Integer, primary_key = True)# 其他字段定义
      
  9. 连接池预Ping配置

    • app.config['SQLALCHEMY_POOL_PRE_PING'] = True:设置为 True 时,SQLAlchemy 在从连接池获取连接时,会先发送一个简单的查询(“预 ping”)来检查连接是否仍然有效。如果连接无效,会自动重新获取一个新的连接。这有助于避免使用已经失效的连接,特别是在数据库服务器可能会主动关闭长时间空闲连接的环境中。

10.3 数据库连接测试

  • run.py

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# 配置数据库连接URL
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://root:root@localhost:3306/test_db'# 关闭 SQLAlchemy 对模型对象修改的跟踪。这样可以减少不必要的资源消耗,提高应用的性能。
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False# 将 SQLAlchemy 与特定的 Flask 应用关联起来,以便在应用中进行数据库操作,如创建模型、执行查询等。
    db = SQLAlchemy(app)
    
  • test_db.py

    使用unittest框架进行测试。

    import unittest
    from run import app,dbclass TestDBConnection(unittest.TestCase):# setUp方法会在每个测试方法执行前被调用def setUp(self):# 获取Flask应用的上下文self.app_context = app.app_context()# 推送应用上下文,确保后续的数据库操作等在Flask应用环境中执行self.app_context.push()# tearDown方法会在每个测试方法执行后被调用def tearDown(self):self.app_context.pop()# 定义测试数据库连接的方法def test_db_connection(self):try:con = db.engine.connect()print(f"数据库连接成功!!连接对象是:{con}")except Exception as e:self.fail(f"数据库连接失败: {str(e)}")finally:con.close()
    

    运行test_db_connection()执行测试。

    • db.engine.connect() 是获取数据库连接对象的关键方法,用于从 SQLAlchemy的连接池中获取一个数据库连接对象。这个连接对象可以用来直接执行SQL语句,与数据库进行交互,比如执行查询、插入、更新和删除等操作。
    • 在 Flask 应用中,通常通过定义模型类(继承自 db.Model)来与数据库交互。但在某些情况下,当你需要执行一些复杂的原生 SQL 查询,或者执行数据库管理操作(如创建表、修改表结构)时,使用 db.engine.connect() 获取连接并执行原生 SQL 语句会更加灵活直接,绕过了模型类的抽象层。

10.4 数据库模型定义

数据库模型类继承自 db.Model,其中 dbSQLAlchemy 的实例。这种继承关系赋予了模型类与数据库交互的能力,使得我们可以通过操作模型类的实例来操作数据库表中的记录。

class UserInfo(db.Model):pass

1. 表名定义

通过 __tablename__ 类属性指定模型类对应的数据库表名。

class UserInfo(db.Model):__tablename__ = 'user_info'

2. 字段定义

模型类的属性对应数据库表的列,通过 db.Column 来定义。db.Column 接受多个参数来指定列的特性:

  1. 数据库类型:指定列的数据类型,如 db.Integer(整数)、db.String(50)(长度为 50 的字符串)、db.TIMESTAMP(时间戳)等。不同的数据类型适用于不同的数据存储需求,例如 db.Integer 适合存储数字 ID,db.String 用于存储文本数据。

  2. 主键:通过设置 primary_key = True 来指定某列为主键。主键是表中唯一标识每一条记录的字段,例如:

    user_id = db.Column(db.Integer, primary_key=True)
    
  3. 自动递增:对于整数类型的主键,通常设置 autoincrement = True 使其值自动递增。每次向表中插入新记录时,该列的值会自动增加,无需手动指定:

    user_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    
  4. 唯一性:使用 unique = True 确保列中的值在表中是唯一的。例如,电子邮件地址通常需要唯一,以避免重复注册:

    email = db.Column(db.String(100), unique=True)
    
  5. 非空约束:通过 nullable = False 表示该列不允许为空值。在插入或更新记录时,如果没有为该列提供值,将会引发错误:

    user_name = db.Column(db.String(50), nullable=False)
    
  6. 默认值:可以使用 default 参数为列设置默认值。当插入记录时,如果没有显式指定该列的值,将使用默认值。例如,为记录创建时间设置默认值为当前时间:

    creation_date = db.Column(db.TIMESTAMP, default=datetime.now)
    

3. 完整示例

from datetime import datetime# 创建SQLAlchemy实例,实际应用中可以不在这里创建,从其他地方导入
db = SQLAlchemy()class UserInfo(db.Model):# 指定该模型类对应的数据库表名为user_info。__tablename__ = 'user_info'user_id = db.Column(db.Integer, primary_key=True, autoincrement=True)user_name = db.Column(db.String(50), nullable=False)password = db.Column(db.String(255), nullable=False)email = db.Column(db.String(100), unique=True, nullable=False)phone_number = db.Column(db.String(20))creation_date = db.Column(db.TIMESTAMP, default=datetime.now)

10.5 数据库会话(Session)

1. 添加数据

  1. 添加单条数据

    通过创建模型实例,然后使用db.session.add()方法将实例添加到会话中,最后调用db.session.commit()提交事务。

    def test_add_user(self):user = UserInfo(user_name='admin', password='admin',email='153578@qq.com',phone_number='18565452652')try:db.session.add(user)db.session.commit()print("用户添加成功~!!")except Exception as e:db.session.rollback()print(f'用户数据添加错误: {str(e)}')
    
  2. 批量添加数据

    批量添加使用db.session.add_all()将包含所有用户信息的列表一次性添加到数据库表中。

    def test_add_users():users_data = [{'username': 'user1', 'email': 'user1@example.com'},{'username': 'user2', 'email': 'user2@example.com'}]users = [User(username=user['username'], email=user['email']) for user in users_data]try:db.session.add_all(users)db.session.commit()print('用户数据添加成功!!')except Exception as e:db.session.rollback()print(f'用户数据添加错误: {str(e)}')
    

2. 查询数据

  1. 获取所有数据

    查询表中所有信息,使用db.session.query(<要查询的表的模型类>).all()

    def test_query_user(self):# 获取所有用户信息users = db.session.query(UserInfo).all()for user in users:print(user.user_name)
    
  2. 获取单个用户信息

    查询单个用户信息使用filter_by().first()通过某个字段值进行查询。

    def test_query_user(self):# 获取单个用户信息user = db.session.query(UserInfo).filter_by(user_id = 5).first()print(user.user_name)
    

3. 更新用户信息

  • 先查询到要更新的实例,修改其属性,然后提交事务。

    def test_update_user(self):user = db.session.query(UserInfo).filter_by(user_id = 5).first()user.email = "jay_hnzz@163.com"db.session.commit()print("用户信息已更新!")
    

4. 删除数据

  • 查询到要删除的实例,使用db.session.delete()方法,然后提交事务。

    def test_delete_user(self):user = db.session.query(UserInfo).filter_by(user_id = 5).first()db.session.delete(user)db.session.commit()print("该用户已注销!")
    

十一、Flask框架web应用完整示例

​ 这是一个基于Flask框架实现用户注册与登录功能的完整示例,前端由HTML构建注册与登录页面,CSS美化样式,JavaScript获取表单数据并通过fetch以 JSON 格式向后端发送请求;后端借助flask_sqlalchemy集成 MySQL数据库,在app/__init__.py配置连接,app/models.py定义UserInfo数据模型,run.py通过/register/login路由分别处理GET请求以渲染页面、POST请求以处理注册登录逻辑,含密码哈希、数据验证、唯一性检查及异常处理,完整呈现Web应用用户认证模块的实现流程。

11.1 项目结构

webproject/
│
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── static/
│   │   ├── login.js
│   │   ├── register.js
│   │   └── styles.css
│   └── templates/
│       ├── login.html
│   	└── register.html
└── run.py

11.2 数据库搭建

-- 创建数据库 test_db,如果数据库已存在则不执行创建操作
CREATE DATABASE IF NOT EXISTS test_db;-- 使用 test_db 数据库
USE test_db;-- 在 test_db 数据库中创建 user_info 表
CREATE TABLE user_info (user_id INT AUTO_INCREMENT PRIMARY KEY,user_name VARCHAR(50) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(100) UNIQUE NOT NULL,phone_number VARCHAR(20),creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

11.3 前端页面

  • 注册页面:register.html

    <!DOCTYPE html>
    <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device - width, initial - scale = 1.0"><link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}"><title>注册</title>
    </head><body>
    <div class="container"><h2>注册</h2><form id="registerForm"><label for="user_name">用户名:</label><input type="text" id="user_name" name="user_name" required><br><label for="password">密码:</label><input type="password" id="password" name="password" required><br><label for="email">邮箱:</label><input type="email" id="email" name="email" required><br><label for="phone_number">电话号码:</label><input type="text" id="phone_number" name="phone_number"><br><input type="submit" value="注册"></form><p>已有账号?<a href="{{ url_for('login') }}">登录</a></p>
    </div>
    <script src="{{ url_for('static', filename='register.js') }}"></script>
    </body></html>
    
  • 登录页面:login.html

    <!DOCTYPE html>
    <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device - width, initial - scale = 1.0"><link rel="stylesheet" href="{{ url_for('static', filename='styles.css')
    }}"><title>登录</title>
    </head><body>
    <div class="container"><h2>登录</h2><form id="loginForm"><label for="user_name">用户名:</label><input type="text" id="user_name" name="user_name" required><br><label for="password">密码:</label><input type="password" id="password" name="password" required><br><input type="submit" value="登录"></form><p>没有账号?<a href="{{ url_for('register') }}">注册</a></p>
    </div>
    <script src="{{ url_for('static', filename='login.js') }}"></script>
    </body></html>
    
  • CSS样式:styles.css

    body {font-family: Arial, sans-serif;background-color: #f4f4f4;display: flex;justify-content: center;align-items: center;min-height: 100vh;margin: 0;
    }.container {background-color: #fff;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);width: 300px;
    }h2 {text-align: center;margin-bottom: 20px;
    }form label {display: block;margin-top: 10px;
    }form input {width: 90%;padding: 10px;margin-top: 5px;margin-bottom: 15px;border: 1px solid #ccc;border-radius: 3px;
    }form input[type="submit"] {background-color: #4CAF50;color: white;cursor: pointer;width: 50%;
    }form input[type="submit"]:hover {background-color: #45a049;
    }p {text-align: center;margin-top: 10px;
    }a {color: #4CAF50;text-decoration: none;
    }a:hover {text-decoration: underline;
    }
    
  • 登录页面JS:login.js

    document.getElementById('loginForm').addEventListener('submit', function (e) {e.preventDefault();const user_name = document.getElementById('user_name').value;const password = document.getElementById('password').value;fetch('{{ url_for("login")}}', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({user_name: user_name,password: password})}).then(response => response.json()).then(data => {if (data.success) {alert('登录成功');} else {alert('登录失败:' + data.message);}});
    });
    
  • 注册页面JS:register.js

    document.getElementById('registerForm').addEventListener('submit', function (e) {e.preventDefault();const user_name = document.getElementById('user_name').value;const password = document.getElementById('password').value;const email = document.getElementById('email').value;const phone_number = document.getElementById('phone_number').value;fetch('{{ url_for("register")}}', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({user_name: user_name, password: password, email: email, phone_number: phone_number})}).then(response => response.json()).then(data => {if (data.success) {alert('注册成功');window.location.href = '/login';} else {alert('注册失败:' + data.message);}});
    });
    

11.4 后端业务

  • 初始化配置模块:__init__.py

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
    # 配置数据库连接字符串,需根据实际情况修改用户名、密码和主机
    app.config['SQLALCHEMY_DATABASE_URI'] ='mysql+mysqlconnector://username:password@localhost:3306/test_db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db = SQLAlchemy(app)
    
  • 数据库模型类:models.py

    from app import dbclass UserInfo(db.Model):__tablename__ = 'user_info'user_id = db.Column(db.Integer, autoincrement=True, primary_key=True)user_name = db.Column(db.String(50), nullable=False)password = db.Column(db.String(255), nullable=False)email = db.Column(db.String(100), unique=True, nullable=False)phone_number = db.Column(db.String(20))creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp())
    
  • 路由及视图函数+主应用入口:run.py

    import hashlib
    from flask import  request, jsonify, render_template
    from app import app, db
    from app.models import UserInfo# 对密码进行哈希处理的函数
    def hash_password(password):# 使用SHA256算法对密码进行哈希,并将结果转换为十六进制字符串return hashlib.sha256(password.encode()).hexdigest()# 根据用户名和哈希后的密码获取用户的函数
    def get_user(user_name, hashed_password):# 在UserInfo表中查询符合条件的用户return UserInfo.query.filter_by(user_name=user_name, password=hashed_password).first()# 注册路由,支持GET和POST请求
    @app.route('/register', methods=['GET', 'POST'])
    def register():if request.method == 'POST':# 获取POST请求中的JSON数据data = request.get_json()# 从JSON数据中提取用户名user_name = data.get('user_name')# 从JSON数据中提取密码password = data.get('password')# 从JSON数据中提取邮箱email = data.get('email')# 从JSON数据中提取电话号码phone_number = data.get('phone_number')# 检查用户名、密码和邮箱是否都存在if not all([user_name, password, email]):return jsonify({'success': False,'message': '用户名、密码和邮箱是必填项'})# 对密码进行哈希处理hashed_password = hash_password(password)# 检查数据库中是否已存在相同用户名或邮箱的用户existing_user = UserInfo.query.filter((UserInfo.user_name == user_name) | (UserInfo.email == email)).first()if existing_user:return jsonify({'success': False,'message': '用户名或邮箱已存在'})# 创建新用户对象new_user = UserInfo(user_name=user_name,password=hashed_password,email=email,phone_number=phone_number)try:# 将新用户添加到数据库会话db.session.add(new_user)# 提交数据库会话,将新用户保存到数据库db.session.commit()return jsonify({'success': True,'message': '注册成功'})except Exception as e:# 如果出现异常,回滚数据库会话db.session.rollback()return jsonify({'success': False,'message': '注册失败:' + str(e)})else:# 如果是GET请求,渲染注册页面return render_template('register.html')# 登录路由,支持GET和POST请求
    @app.route('/login', methods=['GET', 'POST'])
    def login():if request.method == 'POST':# 获取POST请求中的JSON数据data = request.get_json()# 从JSON数据中提取用户名user_name = data.get('user_name')# 从JSON数据中提取密码password = data.get('password')# 检查用户名和密码是否都存在if not all([user_name, password]):return jsonify({'success': False,'message': '用户名和密码是必填项'})# 对密码进行哈希处理hashed_password = hash_password(password)# 根据用户名和哈希后的密码获取用户user = get_user(user_name, hashed_password)if user:return jsonify({'success': True,'message': '登录成功'})else:return jsonify({'success': False,'message': '用户名或密码错误'})else:# 如果是GET请求,渲染登录页面return render_template('login.html')if __name__ == '__main__':# 启动Flask应用,开启调试模式app.run(debug=True)
    

    原创不易,请大家尊重版权,请勿原文抄袭,如有错误地方,欢迎指出,感谢支持。

http://www.dtcms.com/wzjs/48056.html

相关文章:

  • 设计本网站怎么样网站优化包括
  • 简易个人博客网站源码爱站网长尾关键词挖掘查询工具
  • ajax 翻页 wordpress搜索引擎优化与推广技术
  • 企业网站管理系统演示平台天津seo推广优化
  • wordpress google cdn gravator如何网站关键词优化
  • 莱芜网站优化招聘网亚洲精华国产精华液的护肤功效
  • 王烨燃大夫简介湖南网站建设推广优化
  • 一个大佬做的本子网站深圳网站建设专业乐云seo
  • 百度竞价推广价格seo超级外链工具
  • 温州网站建设推广百度安装免费下载
  • 1做网站推广关键词排名优化易下拉技巧
  • 网络推广公司怎么报税常熟seo网站优化软件
  • 聚美优品网站建设方案信息流优化师是做什么的
  • 多种手机网站建设互联网运营培训课程
  • 如何做网站图片关键词优化是怎样收费的
  • 小学网站建设方案书搜狗站长平台
  • 杭州科技公司网站建设百度官方官网
  • wordpress做的网站效果6网站设计报价方案
  • 贸易网站建设企业网站分析报告
  • 一页网站首页图如何做怎么自己创建网址
  • wordpress建站插件网络广告营销的特点
  • 手机怎么做网站精美软文句子
  • 新手20种引流推广方法seo在线优化技术
  • 优质校建设专题网站近期时政热点新闻20条
  • 制作一个网站要多少钱郑州技术支持seo
  • 做网站要不要35类商标深圳seo优化推广
  • 公司响应式网站建设平台网站优化排名方法
  • 南阳专业网站制作费用一般网络推广应该怎么做
  • 南宁市企业网站建设深圳靠谱网站建设公司
  • 岳池住房和城乡建设厅网站国家卫健委最新疫情报告