[ Flask基础面试题目 ]


Django 和 SQLAlchemy 之间比较

1. Django

django的orm是活动记录的方式来实现的, 数据库中的每行数据都直接隐射到代码对象中

2. sqlalchemy

SQLAlcyhemy 是数据映射实现,数据库结构和对象结构之间存在间隙,必须使用另外的持久层来保持与数据库的交互(例如保存对象),不会捆绑并强迫严格遵照活动记录来考量。适用于复杂的查询。

总结

Django 适用于所有常规 CRUD 操作。会自动生成主键,会自动提交等。Django Model 更简洁一些。例如对于类关联,Django 只要直接声明外键,就自动产生关联对象,而 SQLAlcyhemy 要定义外键、relationship 对象,如果有多个外键还要自己指定 join 规则……

flask请求的生命周期

1. 创建ctx = requestContext封装request,session
2. 创建app_ctx = AppContext封装app,g
3. 执行ctx.push将ctx,app_ctx放入local
4. 执行before_request
5. 执行视图函数
6. 执行after_request, 加密session到cookie
7. 销毁ctx和app_ctx

11个钩子信号

'''
请求到来时
1. def wsgi_app--> ctx.push() --> app_ctx 被push到local, 触发appcontext_pushed 信号
    ctx.push里面出问题的捕获信号
    1.1 def wsgi_app --> def handle_exception --> got_request_exception.send(self, exception=e)
    1.2 after_request
    1.3 request_finished

2. def wsgi_app--> self.full_dispatch_request() --> before_first_request 

3. def wsgi_app--> self.full_dispatch_request() --> request_started 信号

4. def wsgi_app--> self.preprocess_request() --> preprocess_request

5. def wsgi_app--> self.preprocess_request() --> before_request

6. 视图函数
    6.1 render_template --> _render -->  before_render_template信号
    6.2 渲染模板
    6.3 render_template --> _render --> template_rendered.send信号 

7. def full_dispatch_request --> def finalize_request --> def process_response -> after_request

8. def full_dispatch_request --> def finalize_request --> request_finished.send(self, response=response)信号

9. pop --> do_teardown_request --> teardown_request_funcs(exc)

10. def wsgi_app --> ctx.pop(error) --> do_teardown_request --> request_tearing_down.send(self, exc=exc)信号

11. def wsgi_app --> ctx.pop(error) --> app_ctx.pop(exc) -->  appcontext_popped.send(self.app) 信号

'''

'''
其他:

一, 视图函数模板渲染
    1.1 render_template --> _render -->  before_render_template信号
    1.2 渲染
    1.3 render_template --> _render --> template_rendered.send信号 


二. 异常处理
    ctx.push时出问题的捕获信号
    1.1 def wsgi_app --> def handle_exception --> got_request_exception.send(self, exception=e)
    1.2 after_request
    1.3 request_finished

'''

简述Flask上下文管理流程?

当 Flask 应用程序启动时,会自动创建应用程序上下文,该上下文是全局唯一的。 当有请求到达 Flask 应用程序时,Flask 会先创建一个请求上下文,并将其绑定到当前线程中。 在请求上下文中,可以访问一些全局对象,如 request、g、current_app 等。这些对象都是线程独立的,不同线程之间互不干扰。 请求上下文中还包含了一些请求相关的信息,如请求头、请求体、请求参数等。 在请求处理过程中,可以通过 g 对象在不同函数之间共享数据,但需要注意避免出现线程安全问题。 请求处理完毕后,Flask 会自动销毁请求上下文,将其从当前线程中解绑,同时清除应用程序上下文。

Flask中的g的作用?

在 Flask 中,g 是一个特殊的全局变量,用于在请求处理过程中共享数据。g 的作用是在同一请求的不同函数之间传递数据,而无需显式地传递参数。

g 存储在当前请求的上下文中,因此它是线程安全的,并且在同一请求的任何地方都可以访问。

使用 g 可以解决以下场景的问题:

共享数据库连接或其他资源:在处理请求时,通常需要与数据库或其他外部资源进行交互。为了避免在每个函数中重复创建和销毁连接的开销,可以将连接存储在 g 中,在不同的函数中复用同一个连接。

from flask import g

@app.route('/')
def index():
    if 'db' not in g:
        g.db = connect_to_database()
    # 使用 g.db 进行数据库操作
    return 'Hello, World!'

临时存储请求相关的数据:在请求处理过程中,可能会产生一些临时数据,需要在多个函数之间共享。例如,验证用户身份并将用户信息存储在 g 中,以便后续的处理函数可以直接访问用户信息。

from flask import g, request

@app.before_request
def authenticate():
    user = authenticate_user(request)
    g.user = user

@app.route('/')
def index():
    # 可以访问 g.user 获取当前用户信息
    return 'Hello, {}!'.format(g.user.username)

需要注意的是,g 的生命周期仅限于当前请求,一旦请求处理完毕,g 中存储的数据会被自动清除。因此,不要将重要的持久化数据存储在 g 中,而应该使用其他方式进行存储,如数据库或会话对象等。

Flask-SQLAlchemy的优化

Flask-SQLAlchemy 在以下方面对 SQLAlchemy 进行了优化:

上下文管理:Flask-SQLAlchemy 与 Flask 上下文管理器的集成,确保在请求处理期间正确管理数据库连接和事务。它提供了自动打开和关闭数据库连接的功能,而无需手动管理这些细节。这样可以减少因未正确管理连接而导致的资源泄漏和性能问题。

查询结果缓存:Flask-SQLAlchemy 支持查询结果的缓存,可避免重复执行相同查询导致的性能损耗。通过使用缓存,可以在多次查询相同数据时,直接从缓存中获取结果,而无需再次访问数据库。

批量插入:Flask-SQLAlchemy 提供了批量插入的支持,可以在一次数据库操作中插入多个记录,而不是逐条插入。这种批量插入的方式可以显著提高插入大量数据的性能,减少了每次插入操作的开销。

延迟加载:Flask-SQLAlchemy 默认使用的是延迟加载(Lazy Loading)模式,即在需要访问关联对象时才从数据库中加载相关数据。这种延迟加载的机制减少了不必要的数据库查询,从而提高了性能。

查询优化:Flask-SQLAlchemy 提供了一些查询优化的功能,如索引、查询缓存等。可以使用索引来提高查询的效率,通过缓存查询结果可以减少数据库访问的次数。

事务管理:Flask-SQLAlchemy 提供了对数据库事务的支持。它通过上下文管理器来自动处理事务的开始、提交和回滚,确保数据的一致性和完整性。

总的来说,Flask-SQLAlchemy 在连接管理、查询结果缓存、批量插入、延迟加载、查询优化和事务管理等方面对 SQLAlchemy 进行了优化。这些优化措施可以提高数据库操作的效率和性能,减少不必要的开销,从而改善应用程序的响应速度和用户体验。