Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into first-request-decorator

Conflicts:
	flask/app.py
  • Loading branch information...
commit 8fd729475c53d57816125a152c29bffb2d34dc3f 2 parents 08e1edc + 0787872
@mfa mfa authored
Showing with 2,244 additions and 556 deletions.
  1. +15 −0 .travis.yml
  2. +39 −9 CHANGES
  3. +1 −1  LICENSE
  4. +10 −1 Makefile
  5. +8 −5 README
  6. +2 −0  docs/_templates/sidebarintro.html
  7. +68 −0 docs/advanced_foreword.rst
  8. +41 −6 docs/api.rst
  9. +88 −0 docs/appcontext.rst
  10. +57 −44 docs/becomingbig.rst
  11. +2 −1  docs/blueprints.rst
  12. +1 −1  docs/conf.py
  13. +21 −2 docs/config.rst
  14. +2 −0  docs/contents.rst.inc
  15. +12 −1 docs/deploying/cgi.rst
  16. +70 −15 docs/deploying/fastcgi.rst
  17. +6 −3 docs/deploying/index.rst
  18. +4 −5 docs/deploying/uwsgi.rst
  19. +63 −33 docs/deploying/{others.rst → wsgi-standalone.rst}
  20. +1 −1  docs/design.rst
  21. +67 −2 docs/errorhandling.rst
  22. +125 −91 docs/extensiondev.rst
  23. +47 −90 docs/foreword.rst
  24. +1 −1  docs/htmlfaq.rst
  25. +32 −32 docs/installation.rst
  26. +20 −2 docs/patterns/appdispatch.rst
  27. +10 −2 docs/patterns/flashing.rst
  28. +1 −1  docs/patterns/jquery.rst
  29. +2 −5 docs/patterns/mongokit.rst
  30. +1 −1  docs/patterns/packages.rst
  31. +23 −0 docs/patterns/streaming.rst
  32. +5 −3 docs/patterns/wtforms.rst
  33. +48 −49 docs/quickstart.rst
  34. +5 −21 docs/reqcontext.rst
  35. +36 −0 docs/signals.rst
  36. +30 −3 docs/templating.rst
  37. +10 −10 docs/tutorial/setup.rst
  38. +22 −0 docs/upgrading.rst
  39. +3 −3 docs/views.rst
  40. +11 −0 examples/blueprintexample/blueprintexample.py
  41. +36 −0 examples/blueprintexample/blueprintexample_test.py
  42. 0  examples/blueprintexample/simple_page/__init__.py
  43. +13 −0 examples/blueprintexample/simple_page/simple_page.py
  44. +5 −0 examples/blueprintexample/simple_page/templates/pages/hello.html
  45. +5 −0 examples/blueprintexample/simple_page/templates/pages/index.html
  46. +25 −0 examples/blueprintexample/simple_page/templates/pages/layout.html
  47. +5 −0 examples/blueprintexample/simple_page/templates/pages/world.html
  48. +7 −4 flask/__init__.py
  49. +191 −23 flask/app.py
  50. +1 −1  flask/blueprints.py
  51. +1 −2  flask/config.py
  52. +124 −8 flask/ctx.py
  53. +49 −0 flask/exceptions.py
  54. +9 −1 flask/globals.py
  55. +234 −29 flask/helpers.py
  56. +1 −0  flask/signals.py
  57. +5 −3 flask/templating.py
  58. +102 −0 flask/testsuite/appctx.py
  59. +105 −13 flask/testsuite/basic.py
  60. +37 −0 flask/testsuite/blueprints.py
  61. +105 −0 flask/testsuite/config.py
  62. +108 −1 flask/testsuite/helpers.py
  63. +6 −3 flask/testsuite/regression.py
  64. +19 −0 flask/testsuite/templating.py
  65. +11 −11 flask/views.py
  66. +14 −4 flask/wrappers.py
  67. +4 −3 scripts/flaskext_compat.py
  68. +7 −4 setup.py
  69. +5 −2 tox.ini
View
15 .travis.yml
@@ -0,0 +1,15 @@
+language: python
+
+python:
+ - 2.5
+ - 2.6
+ - 2.7
+ - pypy
+
+before_install: pip install simplejson
+
+script: python setup.py test
+
+branches:
+ except:
+ - website
View
48 CHANGES
@@ -6,8 +6,10 @@ Here you can see the full list of changes between each Flask release.
Version 0.9
-----------
-Relase date to be decided, codename to be chosen.
+Released on July 1st 2012, codename Campari.
+- The :func:`flask.Request.on_json_loading_failed` now returns a JSON formatted
+ response by default.
- The :func:`flask.url_for` function now can generate anchors to the
generated links.
- The :func:`flask.url_for` function now can also explicitly generate
@@ -42,12 +44,40 @@ Relase date to be decided, codename to be chosen.
using configuration values, e.g. ``app.run(app.config.get('MYHOST'),
app.config.get('MYPORT'))``, with proper behavior whether or not a config
file is provided.
-
+- The :meth:`flask.render_template` method now accepts a either an iterable of
+ template names or a single template name. Previously, it only accepted a
+ single template name. On an iterable, the first template found is rendered.
+- Added :meth:`flask.Flask.app_context` which works very similar to the
+ request context but only provides access to the current application. This
+ also adds support for URL generation without an active request context.
+- View functions can now return a tuple with the first instance being an
+ instance of :class:`flask.Response`. This allows for returning
+ ``jsonify(error="error msg"), 400`` from a view function.
+- :class:`~flask.Flask` and :class:`~flask.Blueprint` now provide a
+ :meth:`~flask.Flask.get_send_file_max_age` hook for subclasses to override
+ behavior of serving static files from Flask when using
+ :meth:`flask.Flask.send_static_file` (used for the default static file
+ handler) and :func:`~flask.helpers.send_file`. This hook is provided a
+ filename, which for example allows changing cache controls by file extension.
+ The default max-age for `send_file` and static files can be configured
+ through a new ``SEND_FILE_MAX_AGE_DEFAULT`` configuration variable, which is
+ used in the default `get_send_file_max_age` implementation.
+- Fixed an assumption in sessions implementation which could break message
+ flashing on sessions implementations which use external storage.
+- Changed the behavior of tuple return values from functions. They are no
+ longer arguments to the response object, they now have a defined meaning.
+- Added :attr:`flask.Flask.request_globals_class` to allow a specific class to
+ be used on creation of the :data:`~flask.g` instance of each request.
+- Added `required_methods` attribute to view functions to force-add methods
+ on registration.
+- Added :func:`flask.after_this_request`.
+- Added :func:`flask.stream_with_context` and the ability to push contexts
+ multiple times without producing unexpected behavior.
Version 0.8.1
-------------
-Bugfix release, release date to be decided
+Bugfix release, released on July 1st 2012
- Fixed an issue with the undocumented `flask.session` module to not
work properly on Python 2.5. It should not be used but did cause
@@ -89,7 +119,7 @@ Released on September 29th 2011, codename Rakija
variable as well as ``SERVER_NAME`` are now properly used by the test client
as defaults.
- Added :attr:`flask.views.View.decorators` to support simpler decorating of
- pluggable (class based) views.
+ pluggable (class-based) views.
- Fixed an issue where the test client if used with the "with" statement did not
trigger the execution of the teardown handlers.
- Added finer control over the session cookie parameters.
@@ -131,7 +161,7 @@ Released on June 28th 2011, codename Grappa
- Added :meth:`~flask.Flask.make_default_options_response`
which can be used by subclasses to alter the default
- behaviour for `OPTIONS` responses.
+ behavior for `OPTIONS` responses.
- Unbound locals now raise a proper :exc:`RuntimeError` instead
of an :exc:`AttributeError`.
- Mimetype guessing and etag support based on file objects is now
@@ -141,7 +171,7 @@ Released on June 28th 2011, codename Grappa
- Static file handling for modules now requires the name of the
static folder to be supplied explicitly. The previous autodetection
was not reliable and caused issues on Google's App Engine. Until
- 1.0 the old behaviour will continue to work but issue dependency
+ 1.0 the old behavior will continue to work but issue dependency
warnings.
- fixed a problem for Flask to run on jython.
- added a `PROPAGATE_EXCEPTIONS` configuration variable that can be
@@ -177,7 +207,7 @@ Released on June 28th 2011, codename Grappa
might occur during request processing (for instance database connection
errors, timeouts from remote resources etc.).
- Blueprints can provide blueprint specific error handlers.
-- Implemented generic :ref:`views` (class based views).
+- Implemented generic :ref:`views` (class-based views).
Version 0.6.1
-------------
@@ -259,14 +289,14 @@ Released on July 6th 2010, codename Calvados
the session cookie cross-subdomain wide.
- autoescaping is no longer active for all templates. Instead it
is only active for ``.html``, ``.htm``, ``.xml`` and ``.xhtml``.
- Inside templates this behaviour can be changed with the
+ Inside templates this behavior can be changed with the
``autoescape`` tag.
- refactored Flask internally. It now consists of more than a
single file.
- :func:`flask.send_file` now emits etags and has the ability to
do conditional responses builtin.
- (temporarily) dropped support for zipped applications. This was a
- rarely used feature and led to some confusing behaviour.
+ rarely used feature and led to some confusing behavior.
- added support for per-package template and static-file directories.
- removed support for `create_jinja_loader` which is no longer used
in 0.5 due to the improved module support.
View
2  LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010 by Armin Ronacher and contributors. See AUTHORS
+Copyright (c) 2012 by Armin Ronacher and contributors. See AUTHORS
for more details.
Some rights reserved.
View
11 Makefile
@@ -23,12 +23,21 @@ clean-pyc:
find . -name '*~' -exec rm -f {} +
upload-docs:
- $(MAKE) -C docs html dirhtml latex
+ $(MAKE) -C docs html dirhtml latex epub
$(MAKE) -C docs/_build/latex all-pdf
cd docs/_build/; mv html flask-docs; zip -r flask-docs.zip flask-docs; mv flask-docs html
rsync -a docs/_build/dirhtml/ pocoo.org:/var/www/flask.pocoo.org/docs/
rsync -a docs/_build/latex/Flask.pdf pocoo.org:/var/www/flask.pocoo.org/docs/flask-docs.pdf
rsync -a docs/_build/flask-docs.zip pocoo.org:/var/www/flask.pocoo.org/docs/flask-docs.zip
+ rsync -a docs/_build/epub/Flask.epub pocoo.org:/var/www/flask.pocoo.org/docs/flask-docs.epub
+
+# ebook-convert docs: http://manual.calibre-ebook.com/cli/ebook-convert.html
+ebook:
+ @echo 'Using .epub from `make upload-docs` to create .mobi.'
+ @echo 'Command `ebook-covert` is provided by calibre package.'
+ @echo 'Requires X-forwarding for Qt features used in conversion (ssh -X).'
+ @echo 'Do not mind "Invalid value for ..." CSS errors if .mobi renders.'
+ ssh -X pocoo.org ebook-convert /var/www/flask.pocoo.org/docs/flask-docs.epub /var/www/flask.pocoo.org/docs/flask-docs.mobi --cover http://flask.pocoo.org/docs/_images/logo-full.png --authors 'Armin Ronacher'
docs:
$(MAKE) -C docs html
View
13 README
@@ -6,7 +6,7 @@
~ What is Flask?
Flask is a microframework for Python based on Werkzeug
- and Jinja2. It's intended for small scale applications
+ and Jinja2. It's intended for getting started very quickly
and was developed with best intentions in mind.
~ Is it ready?
@@ -17,10 +17,11 @@
~ What do I need?
- Jinja 2.4 and Werkzeug 0.6.1. `pip` or `easy_install` will
- install them for you if you do `easy_install Flask`.
- I encourage you to use a virtualenv. Check the docs for
- complete installation and usage instructions.
+ Jinja 2.4 and Werkzeug 0.7 or later.
+ `pip` or `easy_install` will install them for you if you do
+ `pip install Flask`. I encourage you to use a virtualenv.
+ Check the docs for complete installation and usage
+ instructions.
~ Where are the docs?
@@ -50,3 +51,5 @@
Either use the #pocoo IRC channel on irc.freenode.net or
ask on the mailinglist: http://flask.pocoo.org/mailinglist/
+
+ See http://flask.pocoo.org/community/ for more resources.
View
2  docs/_templates/sidebarintro.html
@@ -9,6 +9,8 @@
</p>
<ul>
<li><a href="http://flask.pocoo.org/docs/flask-docs.pdf">as PDF</a>
+ <li><a href="http://flask.pocoo.org/docs/flask-docs.epub">as ePub</a>
+ <li><a href="http://flask.pocoo.org/docs/flask-docs.mobi">as .mobi</a>
<li><a href="http://flask.pocoo.org/docs/flask-docs.zip">as zipped HTML</a>
</ul>
<h3>Useful Links</h3>
View
68 docs/advanced_foreword.rst
@@ -0,0 +1,68 @@
+.. _advanced_foreword:
+
+Foreword for Experienced Programmers
+====================================
+
+Thread-Locals in Flask
+----------------------
+
+One of the design decisions in Flask was that simple tasks should be simple;
+they should not take a lot of code and yet they should not limit you. Because
+of that, Flask has few design choices that some people might find surprising or
+unorthodox. For example, Flask uses thread-local objects internally so that you
+don’t have to pass objects around from function to function within a request in
+order to stay threadsafe. This approach is convenient, but requires a valid
+request context for dependency injection or when attempting to reuse code which
+uses a value pegged to the request. The Flask project is honest about
+thread-locals, does not hide them, and calls out in the code and documentation
+where they are used.
+
+Develop for the Web with Caution
+--------------------------------
+
+Always keep security in mind when building web applications.
+
+If you write a web application, you are probably allowing users to register
+and leave their data on your server. The users are entrusting you with data.
+And even if you are the only user that might leave data in your application,
+you still want that data to be stored securely.
+
+Unfortunately, there are many ways the security of a web application can be
+compromised. Flask protects you against one of the most common security
+problems of modern web applications: cross-site scripting (XSS). Unless you
+deliberately mark insecure HTML as secure, Flask and the underlying Jinja2
+template engine have you covered. But there are many more ways to cause
+security problems.
+
+The documentation will warn you about aspects of web development that require
+attention to security. Some of these security concerns are far more complex
+than one might think, and we all sometimes underestimate the likelihood that a
+vulnerability will be exploited - until a clever attacker figures out a way to
+exploit our applications. And don't think that your application is not
+important enough to attract an attacker. Depending on the kind of attack,
+chances are that automated bots are probing for ways to fill your database with
+spam, links to malicious software, and the like.
+
+Flask is no different from any other framework in that you the developer must
+build with caution, watching for exploits when building to your requirements.
+
+The Status of Python 3
+----------------------
+
+Currently the Python community is in the process of improving libraries to
+support the new iteration of the Python programming language. While the
+situation is greatly improving there are still some issues that make it
+hard for us to switch over to Python 3 just now. These problems are
+partially caused by changes in the language that went unreviewed for too
+long, partially also because we have not quite worked out how the lower-
+level API should change to account for the Unicode differences in Python 3.
+
+Werkzeug and Flask will be ported to Python 3 as soon as a solution for
+the changes is found, and we will provide helpful tips how to upgrade
+existing applications to Python 3. Until then, we strongly recommend
+using Python 2.6 and 2.7 with activated Python 3 warnings during
+development. If you plan on upgrading to Python 3 in the near future we
+strongly recommend that you read `How to write forwards compatible
+Python code <http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/>`_.
+
+Continue to :ref:`installation` or the :ref:`quickstart`.
View
47 docs/api.rst
@@ -265,12 +265,16 @@ Useful Functions and Classes
Points to the application handling the request. This is useful for
extensions that want to support multiple applications running side
- by side.
+ by side. This is powered by the application context and not by the
+ request context, so you can change the value of this proxy by
+ using the :meth:`~flask.Flask.app_context` method.
This is a proxy. See :ref:`notes-on-proxies` for more information.
.. autofunction:: has_request_context
+.. autofunction:: has_app_context
+
.. autofunction:: url_for
.. function:: abort(code)
@@ -285,6 +289,8 @@ Useful Functions and Classes
.. autofunction:: make_response
+.. autofunction:: after_this_request
+
.. autofunction:: send_file
.. autofunction:: send_from_directory
@@ -369,6 +375,11 @@ Extensions
.. versionadded:: 0.8
+Stream Helpers
+--------------
+
+.. autofunction:: stream_with_context
+
Useful Internals
----------------
@@ -412,6 +423,16 @@ Useful Internals
if ctx is not None:
return ctx.session
+.. autoclass:: flask.ctx.AppContext
+ :members:
+
+.. data:: _app_ctx_stack
+
+ Works similar to the request context but only binds the application.
+ This is mainly there for extensions to store data.
+
+ .. versionadded:: 0.9
+
.. autoclass:: flask.blueprints.BlueprintSetupState
:members:
@@ -455,8 +476,18 @@ Signals
.. data:: request_tearing_down
This signal is sent when the application is tearing down the request.
- This is always called, even if an error happened. No arguments are
- provided.
+ This is always called, even if an error happened. An `exc` keyword
+ argument is passed with the exception that caused the teardown.
+
+ .. versionchanged:: 0.9
+ The `exc` parameter was added.
+
+.. data:: appcontext_tearing_down
+
+ This signal is sent when the application is tearing down the
+ application context. This is always called, even if an error happened.
+ An `exc` keyword argument is passed with the exception that caused the
+ teardown.
.. currentmodule:: None
@@ -476,7 +507,7 @@ Signals
.. _blinker: http://pypi.python.org/pypi/blinker
-Class Based Views
+Class-Based Views
-----------------
.. versionadded:: 0.7
@@ -511,7 +542,7 @@ Variable parts are passed to the view function as keyword arguments.
The following converters are available:
=========== ===============================================
-`unicode` accepts any text without a slash (the default)
+`string` accepts any text without a slash (the default)
`int` accepts integers
`float` like `int` but for floating point values
`path` like the default but also accepts slashes
@@ -562,7 +593,7 @@ with the route parameter the view function is defined with the decorator
instead of the `view_func` parameter.
=============== ==========================================================
-`rule` the URL roule as string
+`rule` the URL rule as string
`endpoint` the endpoint for the registered URL rule. Flask itself
assumes that the name of the view function is the name
of the endpoint if not explicitly stated.
@@ -612,6 +643,10 @@ some defaults to :meth:`~flask.Flask.add_url_rule` or general behavior:
decorators that want to customize the `OPTIONS` response on a per-view
basis.
+- `required_methods`: if this attribute is set, Flask will always add
+ these methods when registering a URL rule even if the methods were
+ explicitly overriden in the ``route()`` call.
+
Full example::
def index():
View
88 docs/appcontext.rst
@@ -0,0 +1,88 @@
+.. _app-context:
+
+The Application Context
+=======================
+
+.. versionadded:: 0.9
+
+One of the design ideas behind Flask is that there are two different
+“states” in which code is executed. The application setup state in which
+the application implicitly is on the module level. It starts when the
+:class:`Flask` object is instantiated, and it implicitly ends when the
+first request comes in. While the application is in this state a few
+assumptions are true:
+
+- the programmer can modify the application object safely.
+- no request handling happened so far
+- you have to have a reference to the application object in order to
+ modify it, there is no magic proxy that can give you a reference to
+ the application object you're currently creating or modifying.
+
+On the contrast, during request handling, a couple of other rules exist:
+
+- while a request is active, the context local objects
+ (:data:`flask.request` and others) point to the current request.
+- any code can get hold of these objects at any time.
+
+There is a third state which is sitting in between a little bit.
+Sometimes you are dealing with an application in a way that is similar to
+how you interact with applications during request handling just that there
+is no request active. Consider for instance that you're sitting in an
+interactive Python shell and interacting with the application, or a
+command line application.
+
+The application context is what powers the :data:`~flask.current_app`
+context local.
+
+Purpose of the Application Context
+----------------------------------
+
+The main reason for the application's context existance is that in the
+past a bunch of functionality was attached to the request context in lack
+of a better solution. Since one of the pillar's of Flask's design is that
+you can have more than one application in the same Python process.
+
+So how does the code find the “right” application? In the past we
+recommended passing applications around explicitly, but that caused issues
+with libraries that were not designed with that in mind for libraries for
+which it was too inconvenient to make this work.
+
+A common workaround for that problem was to use the
+:data:`~flask.current_app` proxy later on, which was bound to the current
+request's application reference. Since however creating such a request
+context is an unnecessarily expensive operation in case there is no
+request around, the application context was introduced.
+
+Creating an Application Context
+-------------------------------
+
+To make an application context there are two ways. The first one is the
+implicit one: whenever a request context is pushed, an application context
+will be created alongside if this is necessary. As a result of that, you
+can ignore the existance of the application context unless you need it.
+
+The second way is the explicit way using the
+:meth:`~flask.Flask.app_context` method::
+
+ from flask import Flask, current_app
+
+ app = Flask(__name__)
+ with app.app_context():
+ # within this block, current_app points to app.
+ print current_app.name
+
+The application context is also used by the :func:`~flask.url_for`
+function in case a ``SERVER_NAME`` was configured. This allows you to
+generate URLs even in the absence of a request.
+
+Locality of the Context
+-----------------------
+
+The application context is created and destroyed as necessary. It never
+moves between threads and it will not be shared between requests. As such
+it is the perfect place to store database connection information and other
+things. The internal stack object is called :data:`flask._app_ctx_stack`.
+Extensions are free to store additional information on the topmost level,
+assuming they pick a sufficiently unique name.
+
+For more information about that, see :ref:`extension-dev`.
View
101 docs/becomingbig.rst
@@ -3,45 +3,58 @@
Becoming Big
============
-Your application is becoming more and more complex? If you suddenly
-realize that Flask does things in a way that does not work out for your
-application there are ways to deal with that.
-
-Flask is powered by Werkzeug and Jinja2, two libraries that are in use at
-a number of large websites out there and all Flask does is bring those
-two together. Being a microframework Flask does not do much more than
-combining existing libraries - there is not a lot of code involved.
-What that means for large applications is that it's very easy to take the
-code from Flask and put it into a new module within the applications and
-expand on that.
-
-Flask is designed to be extended and modified in a couple of different
-ways:
-
-- Flask extensions. For a lot of reusable functionality you can create
- extensions. For extensions a number of hooks exist throughout Flask
- with signals and callback functions.
-
-- Subclassing. The majority of functionality can be changed by creating
- a new subclass of the :class:`~flask.Flask` class and overriding
- methods provided for this exact purpose.
-
-- Forking. If nothing else works out you can just take the Flask
- codebase at a given point and copy/paste it into your application
- and change it. Flask is designed with that in mind and makes this
- incredible easy. You just have to take the package and copy it
- into your application's code and rename it (for example to
- `framework`). Then you can start modifying the code in there.
-
-Why consider Forking?
+Here are your options when growing your codebase or scaling your application.
+
+Read the Source.
+----------------
+
+Flask started in part to demonstrate how to build your own framework on top of
+existing well-used tools Werkzeug (WSGI) and Jinja (templating), and as it
+developed, it became useful to a wide audience. As you grow your codebase,
+don't just use Flask -- understand it. Read the source. Flask's code is
+written to be read; it's documentation published so you can use its internal
+APIs. Flask sticks to documented APIs in upstream libraries, and documents its
+internal utilities so that you can find the hook points needed for your
+project.
+
+Hook. Extend.
+-------------
+
+The :ref:`api` docs are full of available overrides, hook points, and
+:ref:`signals`. You can provide custom classes for things like the request and
+response objects. Dig deeper on the APIs you use, and look for the
+customizations which are available out of the box in a Flask release. Look for
+ways in which your project can be refactored into a collection of utilities and
+Flask extensions. Explore the many `extensions
+<http://flask.pocoo.org/extensions/>` in the community, and look for patterns to
+build your own extensions if you do not find the tools you need.
+
+Subclass.
+---------
+
+The :class:`~flask.Flask` class has many methods designed for subclassing. You
+can quickly add or customize behavior by subclassing :class:`~flask.Flask` (see
+the linked method docs) and using that subclass wherever you instantiate an
+application class. This works well with :ref:`app-factories`.
+
+Wrap with middleware.
---------------------
-The majority of code of Flask is within Werkzeug and Jinja2. These
-libraries do the majority of the work. Flask is just the paste that glues
-those together. For every project there is the point where the underlying
-framework gets in the way (due to assumptions the original developers
-had). This is natural because if this would not be the case, the
-framework would be a very complex system to begin with which causes a
+The :ref:`app-dispatch` chapter shows in detail how to apply middleware. You
+can introduce WSGI middleware to wrap your Flask instances and introduce fixes
+and changes at the layer between your Flask application and your HTTP
+server. Werkzeug includes several `middlewares
+<http://werkzeug.pocoo.org/docs/middlewares/>`_.
+
+Fork.
+-----
+
+If none of the above options work, fork Flask. The majority of code of Flask
+is within Werkzeug and Jinja2. These libraries do the majority of the work.
+Flask is just the paste that glues those together. For every project there is
+the point where the underlying framework gets in the way (due to assumptions
+the original developers had). This is natural because if this would not be the
+case, the framework would be a very complex system to begin with which causes a
steep learning curve and a lot of user frustration.
This is not unique to Flask. Many people use patched and modified
@@ -55,8 +68,8 @@ Furthermore integrating upstream changes can be a complex process,
depending on the number of changes. Because of that, forking should be
the very last resort.
-Scaling like a Pro
-------------------
+Scale like a pro.
+-----------------
For many web applications the complexity of the code is less an issue than
the scaling for the number of users or data entries expected. Flask by
@@ -78,11 +91,11 @@ majority of servers are using either threads, greenlets or separate
processes to achieve concurrency which are all methods well supported by
the underlying Werkzeug library.
-Dialogue with the Community
+Discuss with the community.
---------------------------
-The Flask developers are very interested to keep everybody happy, so as
-soon as you find an obstacle in your way, caused by Flask, don't hesitate
-to contact the developers on the mailinglist or IRC channel. The best way
-for the Flask and Flask-extension developers to improve it for larger
+The Flask developers keep the framework accessible to users with codebases big
+and small. If you find an obstacle in your way, caused by Flask, don't hesitate
+to contact the developers on the mailinglist or IRC channel. The best way for
+the Flask and Flask extension developers to improve the tools for larger
applications is getting feedback from users.
View
3  docs/blueprints.rst
@@ -61,7 +61,8 @@ implement a blueprint that does simple rendering of static templates::
from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound
- simple_page = Blueprint('simple_page', __name__)
+ simple_page = Blueprint('simple_page', __name__,
+ template_folder='templates')
@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
View
2  docs/conf.py
@@ -43,7 +43,7 @@
# General information about the project.
project = u'Flask'
-copyright = u'2010, Armin Ronacher'
+copyright = u'2012, Armin Ronacher'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
View
23 docs/config.rst
@@ -95,7 +95,10 @@ The following configuration values are used internally by Flask:
``'myapp.dev:5000'``) Note that
localhost does not support subdomains so
setting this to “localhost” does not
- help.
+ help. Setting a ``SERVER_NAME`` also
+ by default enables URL generation
+ without a request context but with an
+ application context.
``APPLICATION_ROOT`` If the application does not occupy
a whole domain or subdomain this can
be set to the path where the application
@@ -107,6 +110,16 @@ The following configuration values are used internally by Flask:
reject incoming requests with a
content length greater than this by
returning a 413 status code.
+``SEND_FILE_MAX_AGE_DEFAULT``: Default cache control max age to use with
+ :meth:`~flask.Flask.send_static_file` (the
+ default static file handler) and
+ :func:`~flask.send_file`, in
+ seconds. Override this value on a per-file
+ basis using the
+ :meth:`~flask.Flask.get_send_file_max_age`
+ hook on :class:`~flask.Flask` or
+ :class:`~flask.Blueprint`,
+ respectively. Defaults to 43200 (12 hours).
``TRAP_HTTP_EXCEPTIONS`` If this is set to ``True`` Flask will
not execute the error handlers of HTTP
exceptions but instead treat the
@@ -126,6 +139,9 @@ The following configuration values are used internally by Flask:
used to debug those situations. If this
config is set to ``True`` you will get
a regular traceback instead.
+``PREFERRED_URL_SCHEME`` The URL scheme that should be used for
+ URL generation if no URL scheme is
+ available. This defaults to ``http``.
================================= =========================================
.. admonition:: More on ``SERVER_NAME``
@@ -165,6 +181,9 @@ The following configuration values are used internally by Flask:
``SESSION_COOKIE_PATH``, ``SESSION_COOKIE_HTTPONLY``,
``SESSION_COOKIE_SECURE``
+.. versionadded:: 0.9
+ ``PREFERRED_URL_SCHEME``
+
Configuring from Files
----------------------
@@ -267,7 +286,7 @@ configuration::
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
-
+
class DevelopmentConfig(Config):
DEBUG = True
View
2  docs/contents.rst.inc
@@ -9,6 +9,7 @@ instructions for web development with Flask.
:maxdepth: 2
foreword
+ advanced_foreword
installation
quickstart
tutorial/index
@@ -18,6 +19,7 @@ instructions for web development with Flask.
config
signals
views
+ appcontext
reqcontext
blueprints
extensions
View
13 docs/deploying/cgi.rst
@@ -35,12 +35,23 @@ Usually there are two ways to configure the server. Either just copy the
`.cgi` into a `cgi-bin` (and use `mod_rewrite` or something similar to
rewrite the URL) or let the server point to the file directly.
-In Apache for example you can put a like like this into the config:
+In Apache for example you can put something like this into the config:
.. sourcecode:: apache
ScriptAlias /app /path/to/the/application.cgi
+On shared webhosting, though, you might not have access to your Apache config.
+In this case, a file called `.htaccess`, sitting in the public directory you want
+your app to be available, works too but the `ScriptAlias` directive won't
+work in that case:
+
+.. sourcecode:: apache
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-f # Don't interfere with static files
+ RewriteRule ^(.*)$ /path/to/the/application.cgi/$1 [L]
+
For more information consult the documentation of your webserver.
.. _App Engine: http://code.google.com/appengine/
View
85 docs/deploying/fastcgi.rst
@@ -3,12 +3,11 @@
FastCGI
=======
-FastCGI is a deployment option on servers like `nginx`_, `lighttpd`_,
-and `cherokee`_; see :ref:`deploying-uwsgi` and
-:ref:`deploying-other-servers` for other options. To use your WSGI
-application with any of them you will need a FastCGI server first. The
-most popular one is `flup`_ which we will use for this guide. Make sure
-to have it installed to follow along.
+FastCGI is a deployment option on servers like `nginx`_, `lighttpd`_, and
+`cherokee`_; see :ref:`deploying-uwsgi` and :ref:`deploying-wsgi-standalone`
+for other options. To use your WSGI application with any of them you will need
+a FastCGI server first. The most popular one is `flup`_ which we will use for
+this guide. Make sure to have it installed to follow along.
.. admonition:: Watch Out
@@ -52,6 +51,64 @@ can execute it:
# chmod +x /var/www/yourapplication/yourapplication.fcgi
+Configuring Apache
+------------------
+
+The example above is good enough for a basic Apache deployment but your `.fcgi`
+file will appear in your application URL
+e.g. example.com/yourapplication.fcgi/news/. There are few ways to configure
+your application so that yourapplication.fcgi does not appear in the URL. A
+preferable way is to use the ScriptAlias configuration directive::
+
+ <VirtualHost *>
+ ServerName example.com
+ ScriptAlias / /path/to/yourapplication.fcgi/
+ </VirtualHost>
+
+If you cannot set ScriptAlias, for example on an shared web host, you can use
+WSGI middleware to remove yourapplication.fcgi from the URLs. Set .htaccess::
+
+ <IfModule mod_fcgid.c>
+ AddHandler fcgid-script .fcgi
+ <Files ~ (\.fcgi)>
+ SetHandler fcgid-script
+ Options +FollowSymLinks +ExecCGI
+ </Files>
+ </IfModule>
+
+ <IfModule mod_rewrite.c>
+ Options +FollowSymlinks
+ RewriteEngine On
+ RewriteBase /
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^(.*)$ yourapplication.fcgi/$1 [QSA,L]
+ </IfModule>
+
+Set yourapplication.fcgi::
+
+ #!/usr/bin/python
+ #: optional path to your local python site-packages folder
+ import sys
+ sys.path.insert(0, '<your_local_path>/lib/python2.6/site-packages')
+
+ from flup.server.fcgi import WSGIServer
+ from yourapplication import app
+
+ class ScriptNameStripper(object):
+ to_strip = '/yourapplication.fcgi'
+
+ def __init__(self, app):
+ self.app = app
+
+ def __call__(self, environ, start_response):
+ environ['SCRIPT_NAME'] = ''
+ return self.app(environ, start_response)
+
+ app = ScriptNameStripper(app)
+
+ if __name__ == '__main__':
+ WSGIServer(app).run()
+
Configuring lighttpd
--------------------
@@ -74,17 +131,15 @@ A basic FastCGI configuration for lighttpd looks like that::
"^(/static.*)$" => "$1",
"^(/.*)$" => "/yourapplication.fcgi$1"
-Remember to enable the FastCGI, alias and rewrite modules. This
-configuration binds the application to `/yourapplication`. If you want
-the application to work in the URL root you have to work around a
-lighttpd bug with the
+Remember to enable the FastCGI, alias and rewrite modules. This configuration
+binds the application to `/yourapplication`. If you want the application to
+work in the URL root you have to work around a lighttpd bug with the
:class:`~werkzeug.contrib.fixers.LighttpdCGIRootFix` middleware.
Make sure to apply it only if you are mounting the application the URL
-root. Also, see the Lighty docs for more information on `FastCGI and
-Python <http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModFastCGI>`_
-(note that explicitly passing a socket to run() is no longer necessary).
-
+root. Also, see the Lighty docs for more information on `FastCGI and Python
+<http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModFastCGI>`_ (note that
+explicitly passing a socket to run() is no longer necessary).
Configuring nginx
-----------------
@@ -98,7 +153,7 @@ A basic flask FastCGI configuration for nginx looks like this::
location /yourapplication { try_files $uri @yourapplication; }
location @yourapplication {
include fastcgi_params;
- fastcgi_split_path_info ^(/yourapplication)(.*)$;
+ fastcgi_split_path_info ^(/yourapplication)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
View
9 docs/deploying/index.rst
@@ -13,11 +13,14 @@ If you have a different WSGI server look up the server documentation
about how to use a WSGI app with it. Just remember that your
:class:`Flask` application object is the actual WSGI application.
+For hosted options to get up and running quickly, see
+:ref:`quickstart_deployment` in the Quickstart.
+
.. toctree::
:maxdepth: 2
mod_wsgi
- cgi
- fastcgi
+ wsgi-standalone
uwsgi
- others
+ fastcgi
+ cgi
View
9 docs/deploying/uwsgi.rst
@@ -4,11 +4,10 @@ uWSGI
=====
uWSGI is a deployment option on servers like `nginx`_, `lighttpd`_, and
-`cherokee`_; see :ref:`deploying-fastcgi` and
-:ref:`deploying-other-servers` for other options. To use your WSGI
-application with uWSGI protocol you will need a uWSGI server
-first. uWSGI is both a protocol and an application server; the
-application server can serve uWSGI, FastCGI, and HTTP protocols.
+`cherokee`_; see :ref:`deploying-fastcgi` and :ref:`deploying-wsgi-standalone`
+for other options. To use your WSGI application with uWSGI protocol you will
+need a uWSGI server first. uWSGI is both a protocol and an application server;
+the application server can serve uWSGI, FastCGI, and HTTP protocols.
The most popular uWSGI server is `uwsgi`_, which we will use for this
guide. Make sure to have it installed to follow along.
View
96 docs/deploying/others.rst → docs/deploying/wsgi-standalone.rst
@@ -1,11 +1,31 @@
-.. _deploying-other-servers:
+.. _deploying-wsgi-standalone:
-Other Servers
-=============
+Standalone WSGI Containers
+==========================
-There are popular servers written in Python that allow the execution of WSGI
-applications as well. These servers stand alone when they run; you can proxy
-to them from your web server.
+There are popular servers written in Python that contain WSGI applications and
+serve HTTP. These servers stand alone when they run; you can proxy to them
+from your web server. Note the section on :ref:`deploying-proxy-setups` if you
+run into issues.
+
+Gunicorn
+--------
+
+`Gunicorn`_ 'Green Unicorn' is a WSGI HTTP Server for UNIX. It's a pre-fork
+worker model ported from Ruby's Unicorn project. It supports both `eventlet`_
+and `greenlet`_. Running a Flask application on this server is quite simple::
+
+ gunicorn myproject:app
+
+`Gunicorn`_ provides many command-line options -- see ``gunicorn -h``.
+For example, to run a Flask application with 4 worker processes (``-w
+4``) binding to localhost port 4000 (``-b 127.0.0.1:4000``)::
+
+ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
+
+.. _Gunicorn: http://gunicorn.org/
+.. _eventlet: http://eventlet.net/
+.. _greenlet: http://codespeak.net/py/0.9.2/greenlet.html
Tornado
--------
@@ -14,7 +34,7 @@ Tornado
server and tools that power `FriendFeed`_. Because it is non-blocking and
uses epoll, it can handle thousands of simultaneous standing connections,
which means it is ideal for real-time web services. Integrating this
-service with Flask is a trivial task::
+service with Flask is straightforward::
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
@@ -46,44 +66,54 @@ event loop::
.. _greenlet: http://codespeak.net/py/0.9.2/greenlet.html
.. _libevent: http://monkey.org/~provos/libevent/
-Gunicorn
---------
+.. _deploying-proxy-setups:
-`Gunicorn`_ 'Green Unicorn' is a WSGI HTTP Server for UNIX. It's a pre-fork
-worker model ported from Ruby's Unicorn project. It supports both `eventlet`_
-and `greenlet`_. Running a Flask application on this server is quite simple::
+Proxy Setups
+------------
- gunicorn myproject:app
+If you deploy your application using one of these servers behind an HTTP proxy
+you will need to rewrite a few headers in order for the application to work.
+The two problematic values in the WSGI environment usually are `REMOTE_ADDR`
+and `HTTP_HOST`. You can configure your httpd to pass these headers, or you
+can fix them in middleware. Werkzeug ships a fixer that will solve some common
+setups, but you might want to write your own WSGI middleware for specific
+setups.
-`Gunicorn`_ provides many command-line options -- see ``gunicorn -h``.
-For example, to run a Flask application with 4 worker processes (``-w
-4``) binding to localhost port 4000 (``-b 127.0.0.1:4000``)::
+Here's a simple nginx configuration which proxies to an application served on
+localhost at port 8000, setting appropriate headers:
- gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
+.. sourcecode:: nginx
-.. _Gunicorn: http://gunicorn.org/
-.. _eventlet: http://eventlet.net/
-.. _greenlet: http://codespeak.net/py/0.9.2/greenlet.html
+ server {
+ listen 80;
-Proxy Setups
-------------
+ server_name _;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log;
-If you deploy your application using one of these servers behind an HTTP
-proxy you will need to rewrite a few headers in order for the
-application to work. The two problematic values in the WSGI environment
-usually are `REMOTE_ADDR` and `HTTP_HOST`. Werkzeug ships a fixer that
-will solve some common setups, but you might want to write your own WSGI
-middleware for specific setups.
+ location / {
+ proxy_pass http://127.0.0.1:8000/;
+ proxy_redirect off;
-The most common setup invokes the host being set from `X-Forwarded-Host`
-and the remote address from `X-Forwarded-For`::
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+ }
+
+If your httpd is not providing these headers, the most common setup invokes the
+host being set from `X-Forwarded-Host` and the remote address from
+`X-Forwarded-For`::
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
-Please keep in mind that it is a security issue to use such a middleware
-in a non-proxy setup because it will blindly trust the incoming
-headers which might be forged by malicious clients.
+.. admonition:: Trusting Headers
+
+ Please keep in mind that it is a security issue to use such a middleware in
+ a non-proxy setup because it will blindly trust the incoming headers which
+ might be forged by malicious clients.
If you want to rewrite the headers from another header, you might want to
use a fixer like this::
View
2  docs/design.rst
@@ -48,7 +48,7 @@ allocated will be freed again.
Another thing that becomes possible when you have an explicit object lying
around in your code is that you can subclass the base class
-(:class:`~flask.Flask`) to alter specific behaviour. This would not be
+(:class:`~flask.Flask`) to alter specific behavior. 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.
View
69 docs/errorhandling.rst
@@ -1,7 +1,7 @@
.. _application-errors:
-Handling Application Errors
-===========================
+Logging Application Errors
+==========================
.. versionadded:: 0.3
@@ -235,3 +235,68 @@ iterating over them to attach handlers::
for logger in loggers:
logger.addHandler(mail_handler)
logger.addHandler(file_handler)
+
+
+Debugging Application Errors
+============================
+
+For production applications, configure your application with logging and
+notifications as described in :ref:`application-errors`. This section provides
+pointers when debugging deployment configuration and digging deeper with a
+full-featured Python debugger.
+
+
+When in Doubt, Run Manually
+---------------------------
+
+Having problems getting your application configured for production? If you
+have shell access to your host, verify that you can run your application
+manually from the shell in the deployment environment. Be sure to run under
+the same user account as the configured deployment to troubleshoot permission
+issues. You can use Flask's builtin development server with `debug=True` on
+your production host, which is helpful in catching configuration issues, but
+**be sure to do this temporarily in a controlled environment.** Do not run in
+production with `debug=True`.
+
+
+.. _working-with-debuggers:
+
+Working with Debuggers
+----------------------
+
+To dig deeper, possibly to trace code execution, Flask provides a debugger out
+of the box (see :ref:`debug-mode`). If you would like to use another Python
+debugger, note that debuggers interfere with each other. You have to set some
+options in order to use your favorite debugger:
+
+* ``debug`` - whether to enable debug mode and catch exceptinos
+* ``use_debugger`` - whether to use the internal Flask debugger
+* ``use_reloader`` - whether to reload and fork the process on exception
+
+``debug`` must be True (i.e., exceptions must be caught) in order for the other
+two options to have any value.
+
+If you're using Aptana/Eclipse for debugging you'll need to set both
+``use_debugger`` and ``use_reloader`` to False.
+
+A possible useful pattern for configuration is to set the following in your
+config.yaml (change the block as appropriate for your application, of course)::
+
+ FLASK:
+ DEBUG: True
+ DEBUG_WITH_APTANA: True
+
+Then in your application's entry-point (main.py), you could have something like::
+
+ if __name__ == "__main__":
+ # To allow aptana to receive errors, set use_debugger=False
+ app = create_app(config="config.yaml")
+
+ if app.debug: use_debugger = True
+ try:
+ # Disable Flask's debugger if external debugger is requested
+ use_debugger = not(app.config.get('DEBUG_WITH_APTANA'))
+ except:
+ pass
+ app.run(use_debugger=use_debugger, debug=app.debug,
+ use_reloader=use_debugger, host='0.0.0.0')
View
216 docs/extensiondev.rst
@@ -1,3 +1,5 @@
+.. _extension-dev:
+
Flask Extension Development
===========================
@@ -38,17 +40,17 @@ that it works with multiple Flask application instances at once. This is
a requirement because many people will use patterns like the
:ref:`app-factories` pattern to create their application as needed to aid
unittests and to support multiple configurations. Because of that it is
-crucial that your application supports that kind of behaviour.
+crucial that your application supports that kind of behavior.
Most importantly the extension must be shipped with a `setup.py` file and
registered on PyPI. Also the development checkout link should work so
that people can easily install the development version into their
virtualenv without having to download the library by hand.
-Flask extensions must be licensed as BSD or MIT or a more liberal license
-to be enlisted on the Flask Extension Registry. Keep in mind that the
-Flask Extension Registry is a moderated place and libraries will be
-reviewed upfront if they behave as required.
+Flask extensions must be licensed under a BSD, MIT or more liberal license
+to be able to be enlisted in the Flask Extension Registry. Keep in mind
+that the Flask Extension Registry is a moderated place and libraries will
+be reviewed upfront if they behave as required.
"Hello Flaskext!"
-----------------
@@ -125,9 +127,8 @@ Initializing Extensions
-----------------------
Many extensions will need some kind of initialization step. For example,
-consider your application is currently connecting to SQLite like the
-documentation suggests (:ref:`sqlite3`) you will need to provide a few
-functions and before / after request handlers. So how does the extension
+consider an application that's currently connecting to SQLite like the
+documentation suggests (:ref:`sqlite3`). So how does the extension
know the name of the application object?
Quite simple: you pass it to it.
@@ -135,75 +136,106 @@ Quite simple: you pass it to it.
There are two recommended ways for an extension to initialize:
initialization functions:
+
If your extension is called `helloworld` you might have a function
called ``init_helloworld(app[, extra_args])`` that initializes the
extension for that application. It could attach before / after
handlers etc.
classes:
+
Classes work mostly like initialization functions but can later be
- used to further change the behaviour. For an example look at how the
+ used to further change the behavior. For an example look at how the
`OAuth extension`_ works: there is an `OAuth` object that provides
some helper functions like `OAuth.remote_app` to create a reference to
a remote application that uses OAuth.
What to use depends on what you have in mind. For the SQLite 3 extension
-we will use the class based approach because it will provide users with a
-manager object that handles opening and closing database connections.
+we will use the class-based approach because it will provide users with an
+object that handles opening and closing database connections.
+
+What's important about classes is that they encourage to be shared around
+on module level. In that case, the object itself must not under any
+circumstances store any application specific state and must be shareable
+between different application.
The Extension Code
------------------
Here's the contents of the `flask_sqlite3.py` for copy/paste::
- from __future__ import absolute_import
import sqlite3
- from flask import _request_ctx_stack
+ # Find the stack on which we want to store the database connection.
+ # Starting with Flask 0.9, the _app_ctx_stack is the correct one,
+ # before that we need to use the _request_ctx_stack.
+ try:
+ from flask import _app_ctx_stack as stack
+ except ImportError:
+ from flask import _request_ctx_stack as stack
+
class SQLite3(object):
- def __init__(self, app):
- self.app = app
- self.app.config.setdefault('SQLITE3_DATABASE', ':memory:')
- self.app.teardown_request(self.teardown_request)
- self.app.before_request(self.before_request)
+ def __init__(self, app=None):
+ if app is not None:
+ self.app = app
+ self.init_app(self.app)
+ else:
+ self.app = None
+
+ def init_app(self, app):
+ app.config.setdefault('SQLITE3_DATABASE', ':memory:')
+ # Use the newstyle teardown_appcontext if it's available,
+ # otherwise fall back to the request context
+ if hasattr(app, 'teardown_appcontext'):
+ app.teardown_appcontext(self.teardown)
+ else:
+ app.teardown_request(self.teardown)
def connect(self):
return sqlite3.connect(self.app.config['SQLITE3_DATABASE'])
- def before_request(self):
- ctx = _request_ctx_stack.top
- ctx.sqlite3_db = self.connect()
+ def teardown(self, exception):
+ ctx = stack.top
+ if hasattr(ctx, 'sqlite3_db'):
+ ctx.sqlite3_db.close()
- def teardown_request(self, exception):
- ctx = _request_ctx_stack.top
- ctx.sqlite3_db.close()
-
- def get_db(self):
- ctx = _request_ctx_stack.top
+ @property
+ def connection(self):
+ ctx = stack.top
if ctx is not None:
+ if not hasattr(ctx, 'sqlite3_db'):
+ ctx.sqlite3_db = self.connect()
return ctx.sqlite3_db
+
So here's what these lines of code do:
-1. The ``__future__`` import is necessary to activate absolute imports.
- Otherwise we could not call our module `sqlite3.py` and import the
- top-level `sqlite3` module which actually implements the connection to
- SQLite.
-2. We create a class for our extension that requires a supplied `app` object,
- sets a configuration for the database if it's not there
- (:meth:`dict.setdefault`), and attaches `before_request` and
- `teardown_request` handlers.
-3. Next, we define a `connect` function that opens a database connection.
-4. Then we set up the request handlers we bound to the app above. Note here
- that we're attaching our database connection to the top request context via
- `_request_ctx_stack.top`. Extensions should use the top context and not the
- `g` object to store things like database connections.
-5. Finally, we add a `get_db` function that simplifies access to the context's
- database.
-
-So why did we decide on a class based approach here? Because using our
+1. The ``__init__`` method takes an optional app object and, if supplied, will
+ call ``init_app``.
+2. The ``init_app`` method exists so that the ``SQLite3`` object can be
+ instantiated without requiring an app object. This method supports the
+ factory pattern for creating applications. The ``init_app`` will set the
+ configuration for the database, defaulting to an in memory database if
+ no configuration is supplied. In addition, the ``init_app`` method attaches
+ the ``teardown`` handler. It will try to use the newstyle app context
+ handler and if it does not exist, falls back to the request context
+ one.
+3. Next, we define a ``connect`` method that opens a database connection.
+4. Finally, we add a ``connection`` property that on first access opens
+ the database connection and stores it on the context. This is also
+ the recommended way to handling resources: fetch resources lazily the
+ first time they are used.
+
+ Note here that we're attaching our database connection to the top
+ application context via ``_app_ctx_stack.top``. Extensions should use
+ the top context for storing their own information with a sufficiently
+ complex name. Note that we're falling back to the
+ ``_request_ctx_stack.top`` if the application is using an older
+ version of Flask that does not support it.
+
+So why did we decide on a class-based approach here? Because using our
extension looks something like this::
from flask import Flask
@@ -211,71 +243,69 @@ extension looks something like this::
app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
- manager = SQLite3(app)
- db = manager.get_db()
+ db = SQLite3(app)
You can then use the database from views like this::
@app.route('/')
def show_all():
- cur = db.cursor()
+ cur = db.connection.cursor()
cur.execute(...)
-Opening a database connection from outside a view function is simple.
+Likewise if you are outside of a request but you are using Flask 0.9 or
+later with the app context support, you can use the database in the same
+way::
->>> from yourapplication import db
->>> cur = db.cursor()
->>> cur.execute(...)
+ with app.app_context():
+ cur = db.connection.cursor()
+ cur.execute(...)
-Adding an `init_app` Function
------------------------------
+At the end of the `with` block the teardown handles will be executed
+automatically.
-In practice, you'll almost always want to permit users to initialize your
-extension and provide an app object after the fact. This can help avoid
-circular import problems when a user is breaking their app into multiple files.
-Our extension could add an `init_app` function as follows::
+Additionally, the ``init_app`` method is used to support the factory pattern
+for creating apps::
- class SQLite3(object):
+ db = Sqlite3()
+ # Then later on.
+ app = create_app('the-config.cfg')
+ db.init_app(app)
- def __init__(self, app=None):
- if app is not None:
- self.app = app
- self.init_app(self.app)
- else:
- self.app = None
+Keep in mind that supporting this factory pattern for creating apps is required
+for approved flask extensions (described below).
- def init_app(self, app):
- self.app = app
- self.app.config.setdefault('SQLITE3_DATABASE', ':memory:')
- self.app.teardown_request(self.teardown_request)
- self.app.before_request(self.before_request)
+.. admonition:: Note on ``init_app``
- def connect(self):
- return sqlite3.connect(app.config['SQLITE3_DATABASE'])
+ As you noticed, ``init_app`` does not assign ``app`` to ``self``. This
+ is intentional! Class based Flask extensions must only store the
+ application on the object when the application was passed to the
+ constructor. This tells the extension: I am not interested in using
+ multiple applications.
- def before_request(self):
- ctx = _request_ctx_stack.top
- ctx.sqlite3_db = self.connect()
+ When the extension needs to find the current application and it does
+ not have a reference to it, it must either use the
+ :data:`~flask.current_app` context local or change the API in a way
+ that you can pass the application explicitly.
- def teardown_request(self, exception):
- ctx = _request_ctx_stack.top
- ctx.sqlite3_db.close()
- def get_db(self):
- ctx = _request_ctx_stack.top
- if ctx is not None:
- return ctx.sqlite3_db
+Using _app_ctx_stack
+--------------------
-The user could then initialize the extension in one file::
+In the example above, before every request, a ``sqlite3_db`` variable is
+assigned to ``_app_ctx_stack.top``. In a view function, this variable is
+accessible using the ``connection`` property of ``SQLite3``. During the
+teardown of a request, the ``sqlite3_db`` connection is closed. By using
+this pattern, the *same* connection to the sqlite3 database is accessible
+to anything that needs it for the duration of the request.
- manager = SQLite3()
+If the :data:`~flask._app_ctx_stack` does not exist because the user uses
+an old version of Flask, it is recommended to fall back to
+:data:`~flask._request_ctx_stack` which is bound to a request.
-and bind their app to the extension in another file::
-
- manager.init_app(app)
+Teardown Behavior
+-----------------
-End-Of-Request Behavior
------------------------
+*This is only relevant if you want to support Flask 0.6 and older*
Due to the change in Flask 0.7 regarding functions that are run at the end
of the request your extension will have to be extra careful there if it
@@ -326,15 +356,19 @@ new releases. These approved extensions are listed on the `Flask
Extension Registry`_ and marked appropriately. If you want your own
extension to be approved you have to follow these guidelines:
+0. An approved Flask extension requires a maintainer. In the event an
+ extension author would like to move beyond the project, the project should
+ find a new maintainer including full source hosting transition and PyPI
+ access. If no maintainer is available, give access to the Flask core team.
1. An approved Flask extension must provide exactly one package or module
named ``flask_extensionname``. They might also reside inside a
``flaskext`` namespace packages though this is discouraged now.
2. It must ship a testing suite that can either be invoked with ``make test``
or ``python setup.py test``. For test suites invoked with ``make
test`` the extension has to ensure that all dependencies for the test
- are installed automatically, in case of ``python setup.py test``
- dependencies for tests alone can be specified in the `setup.py`
- file. The test suite also has to be part of the distribution.
+ are installed automatically. If tests are invoked with ``python setup.py
+ test``, test dependencies can be specified in the `setup.py` file. The
+ test suite also has to be part of the distribution.
3. APIs of approved extensions will be checked for the following
characteristics:
View
137 docs/foreword.rst
@@ -8,93 +8,50 @@ should or should not be using it.
What does "micro" mean?
-----------------------
-To me, the "micro" in microframework refers not only to the simplicity and
-small size of the framework, but also the fact that it does not make many
-decisions for you. While Flask does pick a templating engine for you, we
-won't make such decisions for your datastore or other parts.
-
-However, to us the term “micro” does not mean that the whole implementation
-has to fit into a single Python file.
-
-One of the design decisions with Flask was that simple tasks should be
-simple; they should not take a lot of code and yet they should not limit you.
-Because of that we made a few design choices that some people might find
-surprising or unorthodox. For example, Flask uses thread-local objects
-internally so that you don't have to pass objects around from function to
-function within a request in order to stay threadsafe. While this is a
-really easy approach and saves you a lot of time, it might also cause some
-troubles for very large applications because changes on these thread-local
-objects can happen anywhere in the same thread. In order to solve these
-problems we don't hide the thread locals for you but instead embrace them
-and provide you with a lot of tools to make it as pleasant as possible to
-work with them.
-
-Flask is also based on convention over configuration, which means that
-many things are preconfigured. For example, by convention templates and
-static files are stored in subdirectories within the application's Python source tree.
-While this can be changed you usually don't have to.
-
-The main reason Flask is called a "microframework" is the idea
-to keep the core simple but extensible. There is no database abstraction
-layer, no form validation or anything else where different libraries
-already exist that can handle that. However Flask supports
-extensions to add such functionality to your application as if it
-was implemented in Flask itself. There are currently extensions for
-object-relational mappers, form validation, upload handling, various open
-authentication technologies and more.
-
-Since Flask is based on a very solid foundation there is not a lot of code
-in Flask itself. As such it's easy to adapt even for large applications
-and we are making sure that you can either configure it as much as
-possible by subclassing things or by forking the entire codebase. If you
-are interested in that, check out the :ref:`becomingbig` chapter.
-
-If you are curious about the Flask design principles, head over to the
-section about :ref:`design`.
-
-Web Development is Dangerous
-----------------------------
-
-I'm not joking. Well, maybe a little. If you write a web
-application, you are probably allowing users to register and leave their
-data on your server. The users are entrusting you with data. And even if
-you are the only user that might leave data in your application, you still
-want that data to be stored securely.
-
-Unfortunately, there are many ways the security of a web application can be
-compromised. Flask protects you against one of the most common security
-problems of modern web applications: cross-site scripting (XSS). Unless
-you deliberately mark insecure HTML as secure, Flask and the underlying
-Jinja2 template engine have you covered. But there are many more ways to
-cause security problems.
-
-The documentation will warn you about aspects of web development that
-require attention to security. Some of these security concerns
-are far more complex than one might think, and we all sometimes underestimate
-the likelihood that a vulnerability will be exploited - until a clever
-attacker figures out a way to exploit our applications. And don't think
-that your application is not important enough to attract an attacker.
-Depending on the kind of attack, chances are that automated bots are
-probing for ways to fill your database with spam, links to malicious
-software, and the like.
-
-So always keep security in mind when doing web development.
-
-The Status of Python 3
-----------------------
-
-Currently the Python community is in the process of improving libraries to
-support the new iteration of the Python programming language. While the
-situation is greatly improving there are still some issues that make it
-hard for us to switch over to Python 3 just now. These problems are
-partially caused by changes in the language that went unreviewed for too
-long, partially also because we have not quite worked out how the lower-
-level API should change to account for the Unicode differences in Python 3.
-
-Werkzeug and Flask will be ported to Python 3 as soon as a solution for
-the changes is found, and we will provide helpful tips how to upgrade
-existing applications to Python 3. Until then, we strongly recommend
-using Python 2.6 and 2.7 with activated Python 3 warnings during
-development. If you plan on upgrading to Python 3 in the near future we
-strongly recommend that you read `How to write forwards compatible
-Python code <http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/>`_.
+“Micro” does not mean that your whole web application has to fit into a single
+Python file, although it certainly can. Nor does it mean that Flask is lacking
+in functionality. The "micro" in microframework means Flask aims to keep the
+core simple but extensible. Flask won't make many decisions for you, such as
+what database to use. Those decisions that it does make, such as what
+templating engine to use, are easy to change. Everything else is up to you, so
+that Flask can be everything you need and nothing you don't.
+
+By default, Flask does not include a database abstraction layer, form
+validation or anything else where different libraries already exist that can
+handle that. Instead, Flask supports extensions to add such functionality to
+your application as if it was implemented in Flask itself. Numerous extensions
+provide database integration, form validation, upload handling, various open
+authentication technologies, and more. Flask may be "micro", but it's ready for
+production use on a variety of needs.
+
+Configuration and Conventions
+-----------------------------
+
+Flask has many configuration values, with sensible defaults, and a few
+conventions when getting started. By convention templates and static files are
+stored in subdirectories within the application's Python source tree, with the
+names `templates` and `static` respectively. While this can be changed you
+usually don't have to, especially when getting started.
+
+Growing with Flask
+------------------
+
+Once you have Flask up and running, you'll find a variety of extensions
+available in the community to integrate your project for production. The Flask
+core team reviews extensions and ensures approved extensions do not break with
+future releases.
+
+As your codebase grows, you are free to make the design decisions appropriate
+for your project. Flask will continue to provide a very simple glue layer to
+the best that Python has to offer. You can implement advanced patterns in
+SQLAlchemy or another database tool, introduce non-relational data persistence
+as appropriate, and take advantage of framework-agnostic tools built for WSGI,
+the Python web interface.
+
+Flask includes many hooks to customize its behavior. Should you need more
+customization, the Flask class is built for subclassing. If you are interested
+in that, check out the :ref:`becomingbig` chapter. If you are curious about
+the Flask design principles, head over to the section about :ref:`design`.
+
+Continue to :ref:`installation`, the :ref:`quickstart`, or the
+:ref:`advanced_foreword`.
View
2  docs/htmlfaq.rst
@@ -52,7 +52,7 @@ Development of the HTML5 specification was started in 2004 under the name
"Web Applications 1.0" by the Web Hypertext Application Technology Working
Group, or WHATWG (which was formed by the major browser vendors Apple,
Mozilla, and Opera) with the goal of writing a new and improved HTML
-specification, based on existing browser behaviour instead of unrealistic
+specification, based on existing browser behavior instead of unrealistic
and backwards-incompatible specifications.
For example, in HTML4 ``<title/Hello/`` theoretically parses exactly the
View
64 docs/installation.rst
@@ -61,27 +61,23 @@ information about how to do that. Once you have it installed, run the same
commands as above, but without the `sudo` prefix.
Once you have virtualenv installed, just fire up a shell and create
-your own environment. I usually create a project folder and an `env`
+your own environment. I usually create a project folder and a `venv`
folder within::
$ mkdir myproject
$ cd myproject
- $ virtualenv env
- New python executable in env/bin/python
- Installing setuptools............done.
+ $ virtualenv venv
+ New python executable in venv/bin/python
+ Installing distribute............done.
Now, whenever you want to work on a project, you only have to activate the
corresponding environment. On OS X and Linux, do the following::
- $ . env/bin/activate
-
-(Note the space between the dot and the script name. The dot means that this
-script should run in the context of the current shell. If this command does
-not work in your shell, try replacing the dot with ``source``.)
+ $ . venv/bin/activate
If you are a Windows user, the following command is for you::
- $ env\scripts\activate
+ $ venv\scripts\activate
Either way, you should now be using your virtualenv (notice how the prompt of
your shell has changed to show the active environment).
@@ -89,7 +85,7 @@ your shell has changed to show the active environment).
Now you can just enter the following command to get Flask activated in your
virtualenv::
- $ easy_install Flask
+ $ pip install Flask
A few seconds later and you are good to go.
@@ -98,19 +94,19 @@ System-Wide Installation
------------------------
This is possible as well, though I do not recommend it. Just run
-`easy_install` with root privileges::
+`pip` with root privileges::
- $ sudo easy_install Flask
+ $ sudo pip install Flask
(On Windows systems, run it in a command-prompt window with administrator
-privleges, and leave out `sudo`.)
+privileges, and leave out `sudo`.)
Living on the Edge
------------------
If you want to work with the latest version of Flask, there are two ways: you
-can either let `easy_install` pull in the development version, or you can tell
+can either let `pip` pull in the development version, or you can tell
it to operate on a git checkout. Either way, virtualenv is recommended.
Get the git checkout in a new virtualenv and run in development mode::
@@ -118,10 +114,10 @@ Get the git checkout in a new virtualenv and run in development mode::
$ git clone http://github.com/mitsuhiko/flask.git
Initialized empty Git repository in ~/dev/flask/.git/
$ cd flask
- $ virtualenv env
- $ . env/bin/activate
- New python executable in env/bin/python
- Installing setuptools............done.
+ $ virtualenv venv --distribute
+ New python executable in venv/bin/python
+ Installing distribute............done.
+ $ . venv/bin/activate
$ python setup.py develop
...
Finished processing dependencies for Flask
@@ -134,23 +130,23 @@ To just get the development version without git, do this instead::
$ mkdir flask
$ cd flask
- $ virtualenv env
- $ . env/bin/activate
- New python executable in env/bin/python
- Installing setuptools............done.
- $ easy_install Flask==dev
+ $ virtualenv venv --distribute
+ $ . venv/bin/activate
+ New python executable in venv/bin/python
+ Installing distribute............done.
+ $ pip install Flask==dev
...
Finished processing dependencies for Flask==dev
.. _windows-easy-install:
-`easy_install` on Windows
--------------------------
+`pip` and `distribute` on Windows
+-----------------------------------
On Windows, installation of `easy_install` is a little bit trickier, but still
-quite easy. The easiest way to do it is to download the `ez_setup.py`_ file
-and run it. The easiest way to run the file is to open your downloads folder
-and double-click on the file.
+quite easy. The easiest way to do it is to download the
+`distribute_setup.py`_ file and run it. The easiest way to run the file is to
+open your downloads folder and double-click on the file.
Next, add the `easy_install` command and other Python scripts to the
command search path, by adding your Python installation's Scripts folder
@@ -161,14 +157,18 @@ Then click on "Advanced System settings" (in Windows XP, click on the
Finally, double-click on the "Path" variable in the "System variables" section,
and add the path of your Python interpreter's Scripts folder. Be sure to
delimit it from existing values with a semicolon. Assuming you are using
-Python 2.6 on the default path, add the following value::
+Python 2.7 on the default path, add the following value::
- ;C:\Python26\Scripts
+ ;C:\Python27\Scripts
And you are done! To check that it worked, open the Command Prompt and execute
``easy_install``. If you have User Account Control enabled on Windows Vista or
Windows 7, it should prompt you for administrator privileges.
+Now that you have ``easy_install``, you can use it to install ``pip``::
+
+ > easy_install pip
+
-.. _ez_setup.py: http://peak.telecommunity.com/dist/ez_setup.py
+.. _distribute_setup.py: http://python-distribute.org/distribute_setup.py
View
22 docs/patterns/appdispatch.rst
@@ -30,6 +30,24 @@ at :func:`werkzeug.serving.run_simple`::
Note that :func:`run_simple <werkzeug.serving.run_simple>` is not intended for
use in production. Use a :ref:`full-blown WSGI server <deployment>`.
+In order to use the interactive debuggger, debugging must be enabled both on
+the application and the simple server, here is the "hello world" example with
+debugging and :func:`run_simple <werkzeug.serving.run_simple>`::
+
+ from flask import Flask
+ from werkzeug.serving import run_simple
+
+ app = Flask(__name__)
+ app.debug = True
+
+ @app.route('/')
+ def hello_world():
+ return 'Hello World!'
+
+ if __name__ == '__main__':
+ run_simple('localhost', 5000, app,
+ use_reloader=True, use_debugger=True, use_evalex=True)
+
Combining Applications
----------------------
@@ -58,7 +76,7 @@ Dispatch by Subdomain
Sometimes you might want to use multiple instances of the same application
with different configurations. Assuming the application is created inside
-a function and you can call that function to instanciate it, that is
+a function and you can call that function to instantiate it, that is
really easy to implement. In order to develop your application to support
creating new instances in functions have a look at the
:ref:`app-factories` pattern.
@@ -72,7 +90,7 @@ the dynamic application creation.
The perfect level for abstraction in that regard is the WSGI layer. You
write your own WSGI application that looks at the request that comes and
-and delegates it to your Flask application. If that application does not
+delegates it to your Flask application. If that application does not
exist yet, it is dynamically created and remembered::
from threading import Lock
View
12 docs/patterns/flashing.rst
@@ -16,7 +16,11 @@ Simple Flashing
So here is a full example::
- from flask import flash, redirect, url_for, render_template
+ from flask import Flask, flash, redirect, render_template, \
+ request, url_for
+
+ app = Flask(__name__)
+ app.secret_key = 'some_secret'
@app.route('/')
def index():
@@ -27,13 +31,17 @@ So here is a full example::
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or \
- request.form['password'] != 'secret':
+ request.form['password'] != 'secret':
error = 'Invalid credentials'
else:
flash('You were successfully logged in')
return redirect(url_for('index'))
return render_template('login.html', error=error)
+ if __name__ == "__main__":
+ app.run()
+
+
And here the ``layout.html`` template which does the magic:
.. sourcecode:: html+jinja
View
2  docs/patterns/jquery.rst
@@ -153,7 +153,7 @@ explanation of the little bit of code above:
2. ``$('selector')`` selects an element and lets you operate on it.
3. ``element.bind('event', func)`` specifies a function that should run
when the user clicked on the element. If that function returns
- `false`, the default behaviour will not kick in (in this case, navigate
+ `false`, the default behavior will not kick in (in this case, navigate
to the `#` URL).
4. ``$.getJSON(url, data, func)`` sends a `GET` request to `url` and will
send the contents of the `data` object as query parameters. Once the
View
7 docs/patterns/mongokit.rst
@@ -17,7 +17,7 @@ here:
Declarative
-----------
-The default behaviour of MongoKit is the declarative one that is based on
+The default behavior of MongoKit is the declarative one that is based on
common ideas from Django or the SQLAlchemy declarative extension.
Here an example `app.py` module for your application::
@@ -122,9 +122,6 @@ collection first, this is somewhat the same as a table in the SQL world.
>>> user = {'name': u'admin', 'email': u'admin@localhost'}
>>> collection.insert(user)
-print list(collection.find())
-print collection.find_one({'name': u'admin'})
-
MongoKit will automatically commit for us.
To query your database, you use the collection directly:
@@ -141,4 +138,4 @@ These results are also dict-like objects:
u'admin@localhost'
For more information about MongoKit, head over to the
-`website <http://bytebucket.org/namlook/mongokit/>`_.
+`website <https://github.com/namlook/mongokit>`_.
View
2  docs/patterns/packages.rst
@@ -55,7 +55,7 @@ following quick checklist:
`__init__.py` file. That way each module can import it safely and the
`__name__` variable will resolve to the correct package.
2. all the view functions (the ones with a :meth:`~flask.Flask.route`
- decorator on top) have to be imported when in the `__init__.py` file.
+ decorator on top) have to be imported in the `__init__.py` file.
Not the object itself, but the module it is in. Import the view module
**after the application object is created**.
View
23 docs/patterns/streaming.rst
@@ -59,3 +59,26 @@ The template is then evaluated as the stream is iterated over. Since each
time you do a yield the server will flush the content to the client you
might want to buffer up a few items in the template which you can do with
``rv.enable_buffering(size)``. ``5`` is a sane default.
+
+Streaming with Context
+----------------------
+
+.. versionadded:: 0.9
+
+Note that when you stream data, the request context is already gone the
+moment the function executes. Flask 0.9 provides you with a helper that
+can keep the request context around during the execution of the
+generator::
+
+ from flask import stream_with_context, request, Response
+
+ @app.route('/stream')
+ def streamed_response():
+ def generate():
+ yield 'Hello '
+ yield request.args['name']
+ yield '!'
+ return Response(stream_with_context(generate()))
+
+Without the :func:`~flask.stream_with_context` function you would get a
+:class:`RuntimeError` at that point.
View
8 docs/patterns/wtforms.rst
@@ -85,8 +85,10 @@ Here's an example `_formhelpers.html` template with such a macro:
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
- <ul class="errors">
- {% for error in field.errors %}<li>{{ error }}{% endfor %}
+ <ul class=errors>
+ {% for error in field.errors %}
+ <li>{{ error }}</li>
+ {% endfor %}
</ul>
{% endif %}
</dd>
@@ -106,7 +108,7 @@ takes advantage of the `_formhelpers.html` template:
.. sourcecode:: html+jinja
{% from "_formhelpers.html" import render_field %}
- <form method="post" action="/register">
+ <form method=post action="/register">
<dl>
{{ render_field(form.username) }}
{{ render_field(form.email) }}
View
97 docs/quickstart.rst
@@ -77,6 +77,8 @@ To stop the server, hit control-C.
This tells your operating system to listen on all public IPs.
+.. _debug-mode:
+
Debug Mode
----------
@@ -112,42 +114,7 @@ Screenshot of the debugger in action:
:class: screenshot
:alt: screenshot of debugger in action
-.. admonition:: Working With Other Debuggers
-
- Debuggers interfere with each other.
- That said, you may still wish to use the debugger in a tool of your choice.
- Flask provides the following options to manage the debug process:
-
- * ``debug`` - whether to enable debug mode and catch exceptinos
- * ``use_debugger`` - whether to use the internal Flask debugger
- * ``use_reloader`` - whether to reload and fork the process on exception
-
- ``debug`` must be True (i.e., exceptions must be caught) in order for the
- other two options to have any value.
-
- If you're using Aptana/Eclipse for debugging you'll need to set both
- ``use_debugger`` and ``use_reloader`` to False.
-
- A possible useful pattern for configuration is to set the following in your
- config.yaml (change the block as approriate for your application, of course)::
-
- FLASK:
- DEBUG: True
- DEBUG_WITH_APTANA: True
-
- Then in your application's entry-point (main.py), you could have something like::
-
- if __name__ == "__main__":
- # To allow aptana to receive errors, set use_debugger=False
- app = create_app(config="config.yaml")
-
- if app.debug: use_debugger = True
- try:
- # Disable Flask's debugger if external debugger is requested
- use_debugger = not(app.config.get('DEBUG_WITH_APTANA'))
- except:
- pass
- app.run(use_debugger=use_debugger, debug=app.debug, use_reloader=use_debugger, host='0.0.0.0')
+Have another debugger in mind? See :ref:`working-with-debuggers`.
Routing
@@ -199,10 +166,10 @@ The following converters exist:
`path` like the default but also accepts slashes
=========== ===========================================
-.. admonition:: Unique URLs / Redirection Behaviour
+.. admonition:: Unique URLs / Redirection Behavior
- Flask's URL rules are based on Werkzeug's routing module. The idea behind
- that module is to ensure beautiful and unique also unique URLs based on
+ Flask's URL rules are based on Werkzeug's routing module. The idea
+ behind that module is to ensure beautiful and unique URLs based on
precedents laid down by Apache and earlier HTTP servers.
Take these two rules::
@@ -226,7 +193,7 @@ The following converters exist:
with a trailing slash will produce a 404 "Not Found" error.
This behavior allows relative URLs to continue working if users access the
- page when they forget a trailing slash, consistent with how with how Apache
+ page when they forget a trailing slash, consistent with how Apache
and other servers work. Also, the URLs will stay unique, which helps search
engines avoid indexing the same page twice.
@@ -267,7 +234,7 @@ some examples:
(This also uses the :meth:`~flask.Flask.test_request_context` method, explained
below. It tells Flask to behave as though it is handling a request, even
-though were are interacting with it through a Python shell. Have a look at the
+though we are interacting with it through a Python shell. Have a look at the
explanation below. :ref:`context-locals`).
Why would you want to build URLs instead of hard-coding them into your
@@ -366,8 +333,7 @@ configured to serve them for you, but during development Flask can do that
as well. Just create a folder called `static` in your package or next to
your module and it will be available at `/static` on the application.
-To generate URLs that part of the URL, use the special ``'static'`` URL
-name::
+To generate URLs for static files, use the special ``'static'`` endpoint name::
url_for('static', filename='style.css')
@@ -548,8 +514,9 @@ attributes mentioned above::
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
- # this is executed if the request method was GET or the
- # credentials were invalid
+ # the code below this is executed if the request method
+ # was GET or the credentials were invalid
+ return render_template('login.html', error=error)
What happens if the key does not exist in the `form` attribute? In that
case a special :exc:`KeyError` is raised. You can catch it like a
@@ -560,7 +527,7 @@ deal with that problem.
To access parameters submitted in the URL (``?key=value``) you can use the
:attr:`~flask.request.args` attribute::
- searchword = request.args.get('q', '')
+ searchword = request.args.get('key', '')
We recommend accessing URL parameters with `get` or by catching the
`KeyError` because users might change the URL and presenting them a 400
@@ -708,8 +675,11 @@ converting return values into response objects is as follows:
returned from the view.
2. If it's a string, a response object is created with that data and the
default parameters.
-3. If a tuple is returned the response object is created by passing the
- tuple as arguments to the response object's constructor.
+3. If a tuple is returned the items in the tuple can provide extra
+ information. Such tuples have to be in the form ``(response, status,
+ headers)`` where at least one item has to be in the tuple. The
+ `status` value will override the status code and `headers` can be a
+ list or dictionary of additional header values.
4. If none of that works, Flask will assume the return value is a
valid WSGI application and convert that into a response object.
@@ -775,7 +745,7 @@ sessions work::
@app.route('/logout')
def logout():
- # remove the username from the session if its there
+ # remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
@@ -798,6 +768,13 @@ not using the template engine (as in this example).
Just take that thing and copy/paste it into your code and you're done.
+A note on cookie-based sessions: Flask will take the values you put into the
+session object and serialize them into a cookie. If you are finding some
+values do not persist across requests, cookies are indeed enabled, and you are
+not getting a clear error message, check the size of the cookie in your page
+responses compared to the size supported by web browsers.
+
+
Message Flashing
----------------
@@ -852,3 +829,25 @@ can do it like this::
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
+
+.. _quickstart_deployment:
+
+Deploying to a Web Server
+-------------------------
+
+Ready to deploy your new Flask app? To wrap up the quickstart, you can
+immediately deploy to a hosted platform, all of which offer a free plan for
+small projects:
+
+- `Deploying Flask on Heroku <http://devcenter.heroku.com/articles/python>`_
+- `Deploying WSGI on dotCloud <http://docs.dotcloud.com/services/python/>`_
+ with `Flask-specific notes <http://flask.pocoo.org/snippets/48/>`_
+
+Other places where you can host your Flask app:
+
+- `Deploying Flask on Webfaction <http://flask.pocoo.org/snippets/65/>`_
+- `Deploying Flask on Google App Engine <https://github.com/kamalgill/flask-appengine-template>`_
+- `Sharing your Localhost Server with Localtunnel <http://flask.pocoo.org/snippets/89/>`_
+
+If you manage your own hosts and would like to host yourself, see the chapter
+on :ref:`deployment`.
View
26 docs/reqcontext.rst
@@ -6,27 +6,7 @@ The Request Context
This document describes the behavior in Flask 0.7 which is mostly in line
with the old behavior but has some small, subtle differences.
-One of the design ideas behind Flask is that there are two different
-“states” in which code is executed. The application setup state in which
-the application implicitly is on the module level. It starts when the
-:class:`Flask` object is instantiated, and it implicitly ends when the
-first request comes in. While the application is in this state a few
-assumptions are true:
-
-- the programmer can modify the application object safely.
-- no request handling happened so far
-- you have to have a reference to the application object in order to
- modify it, there is no magic proxy that can give you a reference to
- the application object you're currently creating or modifying.
-
-On the contrast, during request handling, a couple of other rules exist:
-
-- while a request is active, the context local objects
- (:data:`flask.request` and others) point to the current request.
-- any code can get hold of these objects at any time.
-
-The magic that makes this works is internally referred in Flask as the
-“request context”.
+It is recommended that you read the :ref:`app-context` chapter first.
Diving into Context Locals
--------------------------