Flask中的请求上下文和应用上下文

简介:

Flask中的请求上下文和应用上下文


在Flask中处理请求时,应用会生成一个“请求上下文”对象。整个请求的处理过程,都会在这个上下文对象中进行。这保证了请求的处理过程不被干扰。处理请求的具体代码如下:

 
  1. def wsgi_app(self, environ, start_response): 
  2.  
  3.     with self.request_context(environ): 
  4.  
  5.         # with语句中生成一个`response`对象 
  6.  
  7.         ... 
  8.  
  9.     return response(environ, start_response)  

在Flask 0.9版本之前,应用只有“请求上下文”对象,它包含了和请求处理相关的信息。同时Flask还根据werkzeug.local模块中实现的一种数据结构LocalStack用来存储“请求上下文”对象。这在《一个Flask应用运行过程剖析 》中有所介绍。在0.9版本中,Flask又引入了“应用上下文”的概念。本文主要Flask中的这两个“上下文”对象。

LocalStack

在介绍“请求上下文”和“应用上下文”之前,我们对LocalStack简要做一个回顾。在Werkzeug库——local模块一文中,我们讲解了werkzeug.local模块中实现的三个类Local、LocalStack和LocalProxy。关于它们的概念和详细介绍,可以查看上面的文章。这里,我们用一个例子来说明Flask中使用的一种数据结构LocalStack。

 
  1. >>> from werkzeug.local import LocalStack 
  2.  
  3. >>> import threading 
  4.  
  5.   
  6.  
  7. # 创建一个`LocalStack`对象 
  8.  
  9. >>> local_stack = LocalStack() 
  10.  
  11. # 查看local_stack中存储的信息 
  12.  
  13. >>> local_stack._local.__storage__ 
  14.  
  15. {} 
  16.  
  17.   
  18.  
  19. # 定义一个函数,这个函数可以向`LocalStack`中添加数据 
  20.  
  21. >>> def worker(i): 
  22.  
  23.         local_stack.push(i) 
  24.  
  25.   
  26.  
  27. # 使用3个线程运行函数`worker` 
  28.  
  29. >>> for i in range(3): 
  30.  
  31.         t = threading.Thread(target=worker, args=(i,)) 
  32.  
  33.         t.start() 
  34.  
  35.   
  36.  
  37. # 再次查看local_stack中存储的信息 
  38.  
  39. >>> local_stack._local.__storage__ 
  40.  
  41. {<greenlet.greenlet at 0x4bee5a0>: {'stack': [2]}, 
  42.  
  43. <greenlet.greenlet at 0x4bee638>: {'stack': [1]}, 
  44.  
  45. <greenlet.greenlet at 0x4bee6d0>: {'stack': [0]} 
  46.  
  47. }  

由上面的例子可以看出,存储在LocalStack中的信息以字典的形式存在:键为线程/协程的标识数值,值也是字典形式。每当有一个线程/协程上要将一个对象push进LocalStack栈中,会形成如上一个“键-值”对。这样的一种结构很好地实现了线程/协程的隔离,每个线程/协程都会根据自己线程/协程的标识数值确定存储在栈结构中的值。

LocalStack还实现了push、pop、top等方法。其中top方法永远指向栈顶的元素。栈顶的元素是指当前线程/协程中最后被推入栈中的元素,即local_stack._local.stack[-1](注意,是stack键对应的对象中最后被推入的元素)。

请求上下文

Flask中所有的请求处理都在“请求上下文”中进行,在它设计之初便就有这个概念。由于0.9版本代码比较复杂,这里还是以0.1版本的代码为例进行说明。本质上这两个版本的“请求上下文”的运行原理没有变化,只是新版本增加了一些功能,这点在后面再进行解释。

请求上下文——0.1版本

 
  1. # Flask v0.1 
  2.  
  3. class _RequestContext(object): 
  4.  
  5.     """The request context contains all request relevant information.  It is 
  6.  
  7.     created at the beginning of the request and pushed to the 
  8.  
  9.     `_request_ctx_stack` and removed at the end of it.  It will create the 
  10.  
  11.     URL adapter and request object for the WSGI environment provided. 
  12.  
  13.     ""
  14.  
  15.   
  16.  
  17.     def __init__(self, app, environ): 
  18.  
  19.         self.app = app 
  20.  
  21.         self.url_adapter = app.url_map.bind_to_environ(environ) 
  22.  
  23.         self.request = app.request_class(environ) 
  24.  
  25.         self.session = app.open_session(self.request) 
  26.  
  27.         self.g = _RequestGlobals() 
  28.  
  29.         self.flashes = None 
  30.  
  31.   
  32.  
  33.     def __enter__(self): 
  34.  
  35.         _request_ctx_stack.push(self) 
  36.  
  37.   
  38.  
  39.     def __exit__(self, exc_type, exc_value, tb): 
  40.  
  41.         # do not pop the request stack if we are in debug mode and an 
  42.  
  43.         # exception happened.  This will allow the debugger to still 
  44.  
  45.         # access the request object in the interactive shell. 
  46.  
  47.         if tb is None or not self.app.debug: 
  48.  
  49.             _request_ctx_stack.pop()  

由上面“请求上下文”的实现可知:

  • “请求上下文”是一个上下文对象,实现了__enter__和__exit__方法。可以使用with语句构造一个上下文环境。
  • 进入上下文环境时,_request_ctx_stack这个栈中会推入一个_RequestContext对象。这个栈结构就是上面讲的LocalStack栈。
  • 推入栈中的_RequestContext对象有一些属性,包含了请求的的所有相关信息。例如app、request、session、g、flashes。还有一个url_adapter,这个对象可以进行URL匹配。
  • 在with语句构造的上下文环境中可以进行请求处理。当退出上下文环境时,_request_ctx_stack这个栈会销毁刚才存储的上下文对象。
  • 以上的运行逻辑使得请求的处理始终在一个上下文环境中,这保证了请求处理过程不被干扰,而且请求上下文对象保存在LocalStack栈中,也很好地实现了线程/协程的隔离。

以下是一个简单的例子:

 
  1. # example - Flask v0.1 
  2.  
  3. >>> from flask import Flask, _request_ctx_stack 
  4.  
  5. >>> import threading 
  6.  
  7. >>> app = Flask(__name__) 
  8.  
  9. # 先观察_request_ctx_stack中包含的信息 
  10.  
  11. >>> _request_ctx_stack._local.__storage__ 
  12.  
  13. {} 
  14.  
  15.   
  16.  
  17. # 创建一个函数,用于向栈中推入请求上下文 
  18.  
  19. # 本例中不使用`with`语句 
  20.  
  21. >>> def worker(): 
  22.  
  23.         # 使用应用的test_request_context()方法创建请求上下文 
  24.  
  25.         request_context = app.test_request_context() 
  26.  
  27.         _request_ctx_stack.push(request_context) 
  28.  
  29.   
  30.  
  31. # 创建3个进程分别执行worker方法 
  32.  
  33. >>> for i in range(3): 
  34.  
  35.         t = threading.Thread(target=worker) 
  36.  
  37.         t.start() 
  38.  
  39.   
  40.  
  41. # 再观察_request_ctx_stack中包含的信息 
  42.  
  43. >>> _request_ctx_stack._local.__storage__ 
  44.  
  45. {<greenlet.greenlet at 0x5e45df0>: {'stack': [<flask._RequestContext at 0x710c668>]}, 
  46.  
  47. <greenlet.greenlet at 0x5e45e88>: {'stack': [<flask._RequestContext at 0x7107f28>]}, 
  48.  
  49. <greenlet.greenlet at 0x5e45f20>: {'stack': [<flask._RequestContext at 0x71077f0>]} 
  50.  
  51. }  

上面的结果显示:_request_ctx_stack中为每一个线程创建了一个“键-值”对,每一“键-值”对中包含一个请求上下文对象。如果使用with语句,在离开上下文环境时栈中销毁存储的上下文对象信息。

请求上下文——0.9版本

在0.9版本中,Flask引入了“应用上下文”的概念,这对“请求上下文”的实现有一定的改变。这个版本的“请求上下文”也是一个上下文对象。在使用with语句进入上下文环境后,_request_ctx_stack会存储这个上下文对象。不过与0.1版本相比,有以下几点改变:

  • 请求上下文实现了push、pop方法,这使得对于请求上下文的操作更加的灵活;
  • 伴随着请求上下文对象的生成并存储在栈结构中,Flask还会生成一个“应用上下文”对象,而且“应用上下文”对象也会存储在另一个栈结构中去。这是两个版本最大的不同。

我们先看一下0.9版本相关的代码:

 
  1. # Flask v0.9 
  2.  
  3. def push(self): 
  4.  
  5.     """Binds the request context to the current context.""" 
  6.  
  7.     top = _request_ctx_stack.top 
  8.  
  9.     if top is not None and top.preserved: 
  10.  
  11.         top.pop() 
  12.  
  13.   
  14.  
  15.     # Before we push the request context we have to ensure that there 
  16.  
  17.     # is an application context. 
  18.  
  19.     app_ctx = _app_ctx_stack.top 
  20.  
  21.     if app_ctx is None or app_ctx.app != self.app: 
  22.  
  23.         app_ctx = self.app.app_context() 
  24.  
  25.         app_ctx.push() 
  26.  
  27.         self._implicit_app_ctx_stack.append(app_ctx) 
  28.  
  29.     else
  30.  
  31.         self._implicit_app_ctx_stack.append(None) 
  32.  
  33.   
  34.  
  35.     _request_ctx_stack.push(self) 
  36.  
  37.   
  38.  
  39.     self.session = self.app.open_session(self.request) 
  40.  
  41.     if self.session is None: 
  42.  
  43.         self.session = self.app.make_null_session()  

我们注意到,0.9版本的“请求上下文”的pop方法中,当要将一个“请求上下文”推入_request_ctx_stack栈中的时候,会先检查另一个栈_app_ctx_stack的栈顶是否存在“应用上下文”对象或者栈顶的“应用上下文”对象的应用是否是当前应用。如果不存在或者不是当前对象,Flask会自动先生成一个“应用上下文”对象,并将其推入_app_ctx_stack中。

我们再看离开上下文时的相关代码:

 
  1. # Flask v0.9 
  2.  
  3. def pop(self, exc=None): 
  4.  
  5.     """Pops the request context and unbinds it by doing that.  This will 
  6.  
  7.     also trigger the execution of functions registered by the 
  8.  
  9.     :meth:`~flask.Flask.teardown_request` decorator. 
  10.  
  11.   
  12.  
  13.     .. versionchanged:: 0.9 
  14.  
  15.        Added the `exc` argument. 
  16.  
  17.     ""
  18.  
  19.     app_ctx = self._implicit_app_ctx_stack.pop() 
  20.  
  21.   
  22.  
  23.     clear_request = False 
  24.  
  25.     if not self._implicit_app_ctx_stack: 
  26.  
  27.         self.preserved = False 
  28.  
  29.         if exc is None: 
  30.  
  31.             exc = sys.exc_info()[1] 
  32.  
  33.         self.app.do_teardown_request(exc) 
  34.  
  35.         clear_request = True 
  36.  
  37.   
  38.  
  39.     rv = _request_ctx_stack.pop() 
  40.  
  41.     assert rv is self, 'Popped wrong request context.  (%r instead of %r)' 
  42.  
  43.         % (rv, self) 
  44.  
  45.   
  46.  
  47.     # get rid of circular dependencies at the end of the request 
  48.  
  49.     # so that we don't require the GC to be active. 
  50.  
  51.     if clear_request: 
  52.  
  53.         rv.request.environ['werkzeug.request'] = None 
  54.  
  55.   
  56.  
  57.     # Get rid of the app as well if necessary. 
  58.  
  59.     if app_ctx is not None: 
  60.  
  61.         app_ctx.pop(exc)  

上面代码中的细节先不讨论。注意到当要离开以上“请求上下文”环境的时候,Flask会先将“请求上下文”对象从_request_ctx_stack栈中销毁,之后会根据实际的情况确定销毁“应用上下文”对象。

以下还是以一个简单的例子进行说明:

 
  1. # example - Flask v0.9 
  2.  
  3. >>> from flask import Flask, _request_ctx_stack, _app_ctx_stack 
  4.  
  5. >>> app = Flask(__name__) 
  6.  
  7.   
  8.  
  9. # 先检查两个栈的内容 
  10.  
  11. >>> _request_ctx_stack._local.__storage__ 
  12.  
  13. {} 
  14.  
  15. >>> _app_ctx_stack._local.__storage__ 
  16.  
  17. {} 
  18.  
  19.   
  20.  
  21. # 生成一个请求上下文对象 
  22.  
  23. >>> request_context = app.test_request_context() 
  24.  
  25. >>> request_context.push() 
  26.  
  27.   
  28.  
  29. # 请求上下文推入栈后,再次查看两个栈的内容 
  30.  
  31. >>> _request_ctx_stack._local.__storage__ 
  32.  
  33. {<greenlet.greenlet at 0x6eb32a8>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}} 
  34.  
  35. >>> _app_ctx_stack._local.__storage__ 
  36.  
  37. {<greenlet.greenlet at 0x6eb32a8>: {'stack': [<flask.ctx.AppContext at 0x5c96a58>]}} 
  38.  
  39.   
  40.  
  41. >>> request_context.pop() 
  42.  
  43.   
  44.  
  45. # 销毁请求上下文时,再次查看两个栈的内容 
  46.  
  47. >>> _request_ctx_stack._local.__storage__ 
  48.  
  49. {} 
  50.  
  51. >>> _app_ctx_stack._local.__storage__ 
  52.  
  53. {}  

应用上下文

上部分中简单介绍了“应用上下文”和“请求上下文”的关系。那什么是“应用上下文”呢?我们先看一下它的类:

 
  1. class AppContext(object): 
  2.  
  3.     """The application context binds an application object implicitly 
  4.  
  5.     to the current thread or greenlet, similar to how the 
  6.  
  7.     :class:`RequestContext` binds request information.  The application 
  8.  
  9.     context is also implicitly created if a request context is created 
  10.  
  11.     but the application is not on top of the individual application 
  12.  
  13.     context. 
  14.  
  15.     ""
  16.  
  17.   
  18.  
  19.     def __init__(self, app): 
  20.  
  21.         self.app = app 
  22.  
  23.         self.url_adapter = app.create_url_adapter(None) 
  24.  
  25.   
  26.  
  27.         # Like request context, app contexts can be pushed multiple times 
  28.  
  29.         # but there a basic "refcount" is enough to track them. 
  30.  
  31.         self._refcnt = 0 
  32.  
  33.   
  34.  
  35.     def push(self): 
  36.  
  37.         """Binds the app context to the current context.""" 
  38.  
  39.         self._refcnt += 1 
  40.  
  41.         _app_ctx_stack.push(self) 
  42.  
  43.   
  44.  
  45.     def pop(self, exc=None): 
  46.  
  47.         """Pops the app context.""" 
  48.  
  49.         self._refcnt -= 1 
  50.  
  51.         if self._refcnt <= 0: 
  52.  
  53.             if exc is None: 
  54.  
  55.                 exc = sys.exc_info()[1] 
  56.  
  57.             self.app.do_teardown_appcontext(exc) 
  58.  
  59.         rv = _app_ctx_stack.pop() 
  60.  
  61.         assert rv is self, 'Popped wrong app context.  (%r instead of %r)' \ 
  62.  
  63.             % (rv, self) 
  64.  
  65.   
  66.  
  67.     def __enter__(self):  

由以上代码可以看出:“应用上下文”也是一个上下文对象,可以使用with语句构造一个上下文环境,它也实现了push、pop等方法。“应用上下文”的构造函数也和“请求上下文”类似,都有app、url_adapter等属性。“应用上下文”存在的一个主要功能就是确定请求所在的应用。

然而,以上的论述却又让人产生这样的疑问:既然“请求上下文”中也包含app等和当前应用相关的信息,那么只要调用_request_ctx_stack.top.app或者魔法current_app就可以确定请求所在的应用了,那为什么还需要“应用上下文”对象呢?对于单应用单请求来说,使用“请求上下文”确实就可以了。然而,Flask的设计理念之一就是多应用的支持。当在一个应用的请求上下文环境中,需要嵌套处理另一个应用的相关操作时,“请求上下文”显然就不能很好地解决问题了。如何让请求找到“正确”的应用呢?我们可能会想到,可以再增加一个请求上下文环境,并将其推入_request_ctx_stack栈中。由于两个上下文环境的运行是独立的,不会相互干扰,所以通过调用_request_ctx_stack.top.app或者魔法current_app也可以获得当前上下文环境正在处理哪个应用。这种办法在一定程度上可行,但是如果对于第二个应用的处理不涉及到相关请求,那也就无从谈起“请求上下文”。

为了应对这个问题,Flask中将应用相关的信息单独拿出来,形成一个“应用上下文”对象。这个对象可以和“请求上下文”一起使用,也可以单独拿出来使用。不过有一点需要注意的是:在创建“请求上下文”时一定要创建一个“应用上下文”对象。有了“应用上下文”对象,便可以很容易地确定当前处理哪个应用,这就是魔法current_app。在0.1版本中,current_app是对_request_ctx_stack.top.app的引用,而在0.9版本中current_app是对_app_ctx_stack.top.app的引用。

下面以一个多应用的例子进行说明:

 
  1. # example - Flask v0.9 
  2.  
  3. >>> from flask import Flask, _request_ctx_stack, _app_ctx_stack 
  4.  
  5. # 创建两个Flask应用 
  6.  
  7. >>> app = Flask(__name__) 
  8.  
  9. >>> app2 = Flask(__name__) 
  10.  
  11. # 先查看两个栈中的内容 
  12.  
  13. >>> _request_ctx_stack._local.__storage__ 
  14.  
  15. {} 
  16.  
  17. >>> _app_ctx_stack._local.__storage__ 
  18.  
  19. {} 
  20.  
  21. # 构建一个app的请求上下文环境,在这个环境中运行app2的相关操作 
  22.  
  23. >>> with app.test_request_context(): 
  24.  
  25.         print "Enter app's Request Context:" 
  26.  
  27.         print _request_ctx_stack._local.__storage__ 
  28.  
  29.         print _app_ctx_stack._local.__storage__ 
  30.  
  31.         print 
  32.  
  33.         with app2.app_context(): 
  34.  
  35.             print "Enter app2's App Context:" 
  36.  
  37.             print _request_ctx_stack._local.__storage__ 
  38.  
  39.             print _app_ctx_stack._local.__storage__ 
  40.  
  41.             print 
  42.  
  43.             # do something 
  44.  
  45.         print "Exit app2's App Context:" 
  46.  
  47.         print _request_ctx_stack._local.__storage__ 
  48.  
  49.         print _app_ctx_stack._local.__storage__ 
  50.  
  51.         print 
  52.  
  53. # Result 
  54.  
  55. Enter app's Request Context: 
  56.  
  57. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}} 
  58.  
  59. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>]}} 
  60.  
  61.   
  62.  
  63. Enter app2's App Context: 
  64.  
  65. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}} 
  66.  
  67. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>, <flask.ctx.AppContext object at 0x0000000007313198>]}} 
  68.  
  69.   
  70.  
  71. Exit app2's App Context 
  72.  
  73. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}} 
  74.  
  75. {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>]}}  

在以上的例子中:

  • 我们首先创建了两个Flask应用app和app2;
  • 接着我们构建了一个app的请求上下文环境。当进入这个环境中时,这时查看两个栈的内容,发现两个栈中已经有了当前请求的请求上下文对象和应用上下文对象。并且栈顶的元素都是app的请求上下文和应用上下文;
  • 之后,我们再在这个环境中嵌套app2的应用上下文。当进入app2的应用上下文环境时,两个上下文环境便隔离开来,此时再查看两个栈的内容,发现_app_ctx_stack中推入了app2的应用上下文对象,并且栈顶指向它。这时在app2的应用上下文环境中,current_app便会一直指向app2;
  • 当离开app2的应用上下文环境,_app_ctx_stack栈便会销毁app2的应用上下文对象。这时查看两个栈的内容,发现两个栈中只有app的请求的请求上下文对象和应用上下文对象。
  • 最后,离开app的请求上下文环境后,两个栈便会销毁app的请求的请求上下文对象和应用上下文对象,栈为空。

与上下文对象有关的“全局变量”

在Flask中,为了更加方便地处理一些变量,特地提出了“全局变量”的概念。这些全局变量有:

 
  1. # Flask v0.9 
  2.  
  3. _request_ctx_stack = LocalStack() 
  4.  
  5. _app_ctx_stack = LocalStack() 
  6.  
  7. current_app = LocalProxy(_find_app) 
  8.  
  9. request = LocalProxy(partial(_lookup_object, 'request')) 
  10.  
  11. session = LocalProxy(partial(_lookup_object, 'session')) 
  12.  
  13. g = LocalProxy(partial(_lookup_object, 'g')) 
  14.  
  15.   
  16.  
  17. # 辅助函数 
  18.  
  19. def _lookup_object(name): 
  20.  
  21.     top = _request_ctx_stack.top 
  22.  
  23.     if top is None: 
  24.  
  25.         raise RuntimeError('working outside of request context'
  26.  
  27.     return getattr(topname
  28.  
  29.   
  30.  
  31.   
  32.  
  33. def _find_app(): 
  34.  
  35.     top = _app_ctx_stack.top 
  36.  
  37.     if top is None: 
  38.  
  39.         raise RuntimeError('working outside of application context'
  40.  
  41.     return top.app  

可以看出,Flask中使用的一些“全局变量”,包括current_app、request、session、g等都来自于上下文对象。其中current_app一直指向_app_ctx_stack栈顶的“应用上下文”对象,是对当前应用的引用。而request、session、g等一直指向_request_ctx_stack栈顶的“请求上下文”对象,分别引用请求上下文的request、session和g。不过,从 Flask 0.10 起,对象 g 存储在应用上下文中而不再是请求上下文中。

另外一个问题,在形成这些“全局变量”的时候,使用了werkzeug.local模块的LocalProxy类。之所以要用该类,主要是为了动态地实现对栈顶元素的引用。如果不使用这个类,在生成上述“全局变量”的时候,它们因为指向栈顶元素,而栈顶元素此时为None,所以这些变量也会被设置为None常量。后续即使有上下文对象被推入栈中,相应的“全局变量”也不会发生改变。为了动态地实现对栈顶元素的引用,这里必须使用werkzeug.local模块的LocalProxy类。


作者:佚名

来源:51CTO

相关文章
|
9天前
|
API 数据库 数据安全/隐私保护
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】Django REST framework (DRF) 是用于构建Web API的强力工具,尤其适合Django应用。本文深入讨论DRF面试常见问题,包括视图、序列化、路由、权限控制、分页过滤排序及错误处理。同时,强调了易错点如序列化器验证、权限认证配置、API版本管理、性能优化和响应格式统一,并提供实战代码示例。了解这些知识点有助于在Python面试中展现优秀的Web服务开发能力。
24 1
|
3月前
|
前端开发 数据库 Python
使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
【1月更文挑战第13天】使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
91 7
|
5天前
|
网络架构 Python
在Flask中,如何定义路由并处理HTTP请求的不同方法(GET、POST等)?
【4月更文挑战第25天】在Flask中,使用`@app.route()`装饰器定义路由,如`/hello`,处理GET请求返回&#39;Hello, World!&#39;。通过添加`methods`参数,可处理不同HTTP方法,如POST请求。单一函数可处理多种方法,通过检查`request.method`区分。动态路由使用 `&lt;variable_name&gt;` 传递URL变量到视图函数。这些基础构成处理HTTP请求的Flask应用。
12 1
|
9天前
|
SQL 中间件 API
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】**Flask是Python的轻量级Web框架,以其简洁API和强大扩展性受欢迎。本文深入探讨了面试中关于Flask的常见问题,包括路由、Jinja2模板、数据库操作、中间件和错误处理。同时,提到了易错点,如路由冲突、模板安全、SQL注入,以及请求上下文管理。通过实例代码展示了如何创建和管理数据库、使用表单以及处理请求。掌握这些知识将有助于在面试中展现Flask技能。**
14 1
Flask框架在Python面试中的应用与实战
|
12天前
|
JSON 数据格式 Python
如何在Flask框架中定义路由和处理请求?
【4月更文挑战第18天】在Flask框架中,创建应用实例、定义路由和处理请求涉及5个步骤:1) 导入Flask并实例化应用;2) 使用`app.route()`装饰器定义路由,指定URL和HTTP方法;3) 编写视图函数处理请求逻辑;4) 视图函数返回响应内容,Flask会自动转换格式;5) 用`app.run()`启动服务器。
21 3
|
14天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
14天前
|
监控 安全 数据库
Flask应用部署指南:从开发到生产环境
【4月更文挑战第16天】本文是Flask应用从开发到生产的部署指南,涵盖开发环境准备、应用开发、部署方案选择、生产环境配置、应用部署、监控与维护。确保安装Python、Flask及依赖库,使用文本编辑器或IDE编写代码,关注应用安全与性能。选择WSGI服务器、Docker或云服务平台部署,配置生产环境,确保安全性,然后部署应用并进行监控维护,定期更新修复问题,保证应用稳定运行。
|
14天前
|
JSON 安全 API
Flask-Login与Flask-RESTful:扩展你的应用功能
【4月更文挑战第16天】本文介绍了两个实用的Flask扩展——Flask-Login和Flask-RESTful。Flask-Login提供用户认证和会话管理,简化了登录、注销和保护路由的逻辑。而Flask-RESTful则助力构建RESTful API,支持多种HTTP方法和请求解析。通过这两个扩展,开发者能轻松增强Flask应用的功能性,实现安全的用户认证和高效的API交互。
|
15天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
1月前
|
存储 Java UED
如何在Flask应用中实现异步编程?
【2月更文挑战第27天】【2月更文挑战第96篇】如何在Flask应用中实现异步编程?