Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/studio/static/doc/flask-docs/design.html
blob: b5dd47905e5d6bc3653178550923de1ad56e1440 (plain)
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Design Decisions in Flask &mdash; Flask 0.8 documentation</title>
    
    <link rel="stylesheet" href="_static/flasky.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '',
        VERSION:     '0.8',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Flask 0.8 documentation" href="index.html" />
    <link rel="next" title="HTML/XHTML FAQ" href="htmlfaq.html" />
    <link rel="prev" title="API" href="api.html" />
   
  
  <link rel="apple-touch-icon" href="_static/touch-icon.png" />
  
  <link media="only screen and (max-device-width: 480px)" href="_static/small_flask.css" type= "text/css" rel="stylesheet" />

  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="htmlfaq.html" title="HTML/XHTML FAQ"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="api.html" title="API"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Flask 0.8 documentation</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="design-decisions-in-flask">
<span id="design"></span><h1>Design Decisions in Flask<a class="headerlink" href="#design-decisions-in-flask" title="Permalink to this headline">¶</a></h1>
<p>If you are curious why Flask does certain things the way it does and not
differently, this section is for you.  This should give you an idea about
some of the design decisions that may appear arbitrary and surprising at
first, especially in direct comparison with other frameworks.</p>
<div class="section" id="the-explicit-application-object">
<h2>The Explicit Application Object<a class="headerlink" href="#the-explicit-application-object" title="Permalink to this headline">¶</a></h2>
<p>A Python web application based on WSGI has to have one central callable
object that implements the actual application.  In Flask this is an
instance of the <a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><tt class="xref py py-class docutils literal"><span class="pre">Flask</span></tt></a> class.  Each Flask application has
to create an instance of this class itself and pass it the name of the
module, but why can&#8217;t Flask do that itself?</p>
<p>Without such an explicit application object the following code:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>

<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
    <span class="k">return</span> <span class="s">&#39;Hello World!&#39;</span>
</pre></div>
</div>
<p>Would look like this instead:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">hypothetical_flask</span> <span class="kn">import</span> <span class="n">route</span>

<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
    <span class="k">return</span> <span class="s">&#39;Hello World!&#39;</span>
</pre></div>
</div>
<p>There are three major reasons for this.  The most important one is that
implicit application objects require that there may only be one instance at
the time.  There are ways to fake multiple applications with a single
application object, like maintaining a stack of applications, but this
causes some problems I won&#8217;t outline here in detail.  Now the question is:
when does a microframework need more than one application at the same
time?  A good example for this is unittesting.  When you want to test
something it can be very helpful to create a minimal application to test
specific behavior.  When the application object is deleted everything it
allocated will be freed again.</p>
<p>Another thing that becomes possible when you have an explicit object lying
around in your code is that you can subclass the base class
(<a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><tt class="xref py py-class docutils literal"><span class="pre">Flask</span></tt></a>) to alter specific behaviour.  This would not be
possible without hacks if the object were created ahead of time for you
based on a class that is not exposed to you.</p>
<p>But there is another very important reason why Flask depends on an
explicit instantiation of that class: the package name.  Whenever you
create a Flask instance you usually pass it <cite>__name__</cite> as package name.
Flask depends on that information to properly load resources relative
to your module.  With Python&#8217;s outstanding support for reflection it can
then access the package to figure out where the templates and static files
are stored (see <a class="reference internal" href="api.html#flask.Flask.open_resource" title="flask.Flask.open_resource"><tt class="xref py py-meth docutils literal"><span class="pre">open_resource()</span></tt></a>).  Now obviously there
are frameworks around that do not need any configuration and will still be
able to load templates relative to your application module.  But they have
to use the current working directory for that, which is a very unreliable
way to determine where the application is.  The current working directory
is process-wide and if you are running multiple applications in one
process (which could happen in a webserver without you knowing) the paths
will be off.  Worse: many webservers do not set the working directory to
the directory of your application but to the document root which does not
have to be the same folder.</p>
<p>The third reason is &#8220;explicit is better than implicit&#8221;.  That object is
your WSGI application, you don&#8217;t have to remember anything else.  If you
want to apply a WSGI middleware, just wrap it and you&#8217;re done (though
there are better ways to do that so that you do not lose the reference
to the application object <a class="reference internal" href="api.html#flask.Flask.wsgi_app" title="flask.Flask.wsgi_app"><tt class="xref py py-meth docutils literal"><span class="pre">wsgi_app()</span></tt></a>).</p>
<p>Furthermore this design makes it possible to use a factory function to
create the application which is very helpful for unittesting and similar
things (<a class="reference internal" href="patterns/appfactories.html#app-factories"><em>Application Factories</em></a>).</p>
</div>
<div class="section" id="the-routing-system">
<h2>The Routing System<a class="headerlink" href="#the-routing-system" title="Permalink to this headline">¶</a></h2>
<p>Flask uses the Werkzeug routing system which has was designed to
automatically order routes by complexity.  This means that you can declare
routes in arbitrary order and they will still work as expected.  This is a
requirement if you want to properly implement decorator based routing
since decorators could be fired in undefined order when the application is
split into multiple modules.</p>
<p>Another design decision with the Werkzeug routing system is that routes
in Werkzeug try to ensure that there is that URLs are unique.  Werkzeug
will go quite far with that in that it will automatically redirect to a
canonical URL if a route is ambiguous.</p>
</div>
<div class="section" id="one-template-engine">
<h2>One Template Engine<a class="headerlink" href="#one-template-engine" title="Permalink to this headline">¶</a></h2>
<p>Flask decides on one template engine: Jinja2.  Why doesn&#8217;t Flask have a
pluggable template engine interface?  You can obviously use a different
template engine, but Flask will still configure Jinja2 for you.  While
that limitation that Jinja2 is <em>always</em> configured will probably go away,
the decision to bundle one template engine and use that will not.</p>
<p>Template engines are like programming languages and each of those engines
has a certain understanding about how things work.  On the surface they
all work the same: you tell the engine to evaluate a template with a set
of variables and take the return value as string.</p>
<p>But that&#8217;s about where similarities end.  Jinja2 for example has an
extensive filter system, a certain way to do template inheritance, support
for reusable blocks (macros) that can be used from inside templates and
also from Python code, uses Unicode for all operations, supports
iterative template rendering, configurable syntax and more.  On the other
hand an engine like Genshi is based on XML stream evaluation, template
inheritance by taking the availability of XPath into account and more.
Mako on the other hand treats templates similar to Python modules.</p>
<p>When it comes to connecting a template engine with an application or
framework there is more than just rendering templates.  For instance,
Flask uses Jinja2&#8217;s extensive autoescaping support.  Also it provides
ways to access macros from Jinja2 templates.</p>
<p>A template abstraction layer that would not take the unique features of
the template engines away is a science on its own and a too large
undertaking for a microframework like Flask.</p>
<p>Furthermore extensions can then easily depend on one template language
being present.  You can easily use your own templating language, but an
extension could still depend on Jinja itself.</p>
</div>
<div class="section" id="micro-with-dependencies">
<h2>Micro with Dependencies<a class="headerlink" href="#micro-with-dependencies" title="Permalink to this headline">¶</a></h2>
<p>Why does Flask call itself a microframework and yet it depends on two
libraries (namely Werkzeug and Jinja2).  Why shouldn&#8217;t it?  If we look
over to the Ruby side of web development there we have a protocol very
similar to WSGI.  Just that it&#8217;s called Rack there, but besides that it
looks very much like a WSGI rendition for Ruby.  But nearly all
applications in Ruby land do not work with Rack directly, but on top of a
library with the same name.  This Rack library has two equivalents in
Python: WebOb (formerly Paste) and Werkzeug.  Paste is still around but
from my understanding it&#8217;s sort of deprecated in favour of WebOb.  The
development of WebOb and Werkzeug started side by side with similar ideas
in mind: be a good implementation of WSGI for other applications to take
advantage.</p>
<p>Flask is a framework that takes advantage of the work already done by
Werkzeug to properly interface WSGI (which can be a complex task at
times).  Thanks to recent developments in the Python package
infrastructure, packages with dependencies are no longer an issue and
there are very few reasons against having libraries that depend on others.</p>
</div>
<div class="section" id="thread-locals">
<h2>Thread Locals<a class="headerlink" href="#thread-locals" title="Permalink to this headline">¶</a></h2>
<p>Flask uses thread local objects (context local objects in fact, they
support greenlet contexts as well) for request, session and an extra
object you can put your own things on (<a class="reference internal" href="api.html#flask.g" title="flask.g"><tt class="xref py py-data docutils literal"><span class="pre">g</span></tt></a>).  Why is that and
isn&#8217;t that a bad idea?</p>
<p>Yes it is usually not such a bright idea to use thread locals.  They cause
troubles for servers that are not based on the concept of threads and make
large applications harder to maintain.  However Flask is just not designed
for large applications or asynchronous servers.  Flask wants to make it
quick and easy to write a traditional web application.</p>
<p>Also see the <a class="reference internal" href="becomingbig.html#becomingbig"><em>Becoming Big</em></a> section of the documentation for some
inspiration for larger applications based on Flask.</p>
</div>
<div class="section" id="what-flask-is-what-flask-is-not">
<h2>What Flask is, What Flask is Not<a class="headerlink" href="#what-flask-is-what-flask-is-not" title="Permalink to this headline">¶</a></h2>
<p>Flask will never have a database layer.  It will not have a form library
or anything else in that direction.  Flask itself just bridges to Werkzeug
to implement a proper WSGI application and to Jinja2 to handle templating.
It also binds to a few common standard library packages such as logging.
Everything else is up for extensions.</p>
<p>Why is this the case?  Because people have different preferences and
requirements and Flask could not meet those if it would force any of this
into the core.  The majority of web applications will need a template
engine in some sort.  However not every application needs a SQL database.</p>
<p>The idea of Flask is to build a good foundation for all applications.
Everything else is up to you or extensions.</p>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper"><p class="logo"><a href="index.html">
  <img class="logo" src="_static/flask.png" alt="Logo"/>
</a></p>
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Design Decisions in Flask</a><ul>
<li><a class="reference internal" href="#the-explicit-application-object">The Explicit Application Object</a></li>
<li><a class="reference internal" href="#the-routing-system">The Routing System</a></li>
<li><a class="reference internal" href="#one-template-engine">One Template Engine</a></li>
<li><a class="reference internal" href="#micro-with-dependencies">Micro with Dependencies</a></li>
<li><a class="reference internal" href="#thread-locals">Thread Locals</a></li>
<li><a class="reference internal" href="#what-flask-is-what-flask-is-not">What Flask is, What Flask is Not</a></li>
</ul>
</li>
</ul>
<h3>Related Topics</h3>
<ul>
  <li><a href="index.html">Documentation overview</a><ul>
      <li>Previous: <a href="api.html" title="previous chapter">API</a></li>
      <li>Next: <a href="htmlfaq.html" title="next chapter">HTML/XHTML FAQ</a></li>
  </ul></li>
</ul>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/design.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="footer">
      &copy; Copyright 2010, Armin Ronacher.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
    </div>
  </body>
</html>