Merge branch 'master' into celery-documentation

This commit is contained in:
David Lord 2017-05-15 12:17:09 -07:00
commit f13e3fc352
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
81 changed files with 1642 additions and 803 deletions

View file

@ -16,7 +16,7 @@
<h3>Useful Links</h3>
<ul>
<li><a href="http://flask.pocoo.org/">The Flask Website</a></li>
<li><a href="http://pypi.python.org/pypi/Flask">Flask @ PyPI</a></li>
<li><a href="http://github.com/pallets/flask">Flask @ GitHub</a></li>
<li><a href="http://github.com/pallets/flask/issues">Issue Tracker</a></li>
<li><a href="https://pypi.python.org/pypi/Flask">Flask @ PyPI</a></li>
<li><a href="https://github.com/pallets/flask">Flask @ GitHub</a></li>
<li><a href="https://github.com/pallets/flask/issues">Issue Tracker</a></li>
</ul>

View file

@ -30,61 +30,12 @@ Incoming Request Data
.. autoclass:: Request
:members:
.. attribute:: form
A :class:`~werkzeug.datastructures.MultiDict` with the parsed form data from ``POST``
or ``PUT`` requests. Please keep in mind that file uploads will not
end up here, but instead in the :attr:`files` attribute.
.. attribute:: args
A :class:`~werkzeug.datastructures.MultiDict` with the parsed contents of the query
string. (The part in the URL after the question mark).
.. attribute:: values
A :class:`~werkzeug.datastructures.CombinedMultiDict` with the contents of both
:attr:`form` and :attr:`args`.
.. attribute:: cookies
A :class:`dict` with the contents of all cookies transmitted with
the request.
.. attribute:: stream
If the incoming form data was not encoded with a known mimetype
the data is stored unmodified in this stream for consumption. Most
of the time it is a better idea to use :attr:`data` which will give
you that data as a string. The stream only returns the data once.
.. attribute:: headers
The incoming request headers as a dictionary like object.
.. attribute:: data
Contains the incoming request data as string in case it came with
a mimetype Flask does not handle.
.. attribute:: files
A :class:`~werkzeug.datastructures.MultiDict` with files uploaded as part of a
``POST`` or ``PUT`` request. Each file is stored as
:class:`~werkzeug.datastructures.FileStorage` object. It basically behaves like a
standard file object you know from Python, with the difference that
it also has a :meth:`~werkzeug.datastructures.FileStorage.save` function that can
store the file on the filesystem.
:inherited-members:
.. attribute:: environ
The underlying WSGI environment.
.. attribute:: method
The current request method (``POST``, ``GET`` etc.)
.. attribute:: path
.. attribute:: full_path
.. attribute:: script_root
@ -114,15 +65,8 @@ Incoming Request Data
`url_root` ``u'http://www.example.com/myapplication/'``
============= ======================================================
.. attribute:: is_xhr
``True`` if the request was triggered via a JavaScript
`XMLHttpRequest`. This only works with libraries that support the
``X-Requested-With`` header and set it to `XMLHttpRequest`.
Libraries that do that are prototype, jQuery and Mochikit and
probably some more.
.. class:: request
.. attribute:: request
To access incoming request data, you can use the global `request`
object. Flask parses incoming request data for you and gives you

View file

@ -12,7 +12,7 @@ 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 is published so you can use its internal
written to be read; its documentation is 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.

View file

@ -177,11 +177,11 @@ the `template_folder` parameter to the :class:`Blueprint` constructor::
admin = Blueprint('admin', __name__, template_folder='templates')
For static files, the path can be absolute or relative to the blueprint
resource folder.
resource folder.
The template folder is added to the search path of templates but with a lower
priority than the actual application's template folder. That way you can
easily override templates that a blueprint provides in the actual application.
The template folder is added to the search path of templates but with a lower
priority than the actual application's template folder. That way you can
easily override templates that a blueprint provides in the actual application.
This also means that if you don't want a blueprint template to be accidentally
overridden, make sure that no other blueprint or actual application template
has the same relative path. When multiple blueprints provide the same relative
@ -194,7 +194,7 @@ want to render the template ``'admin/index.html'`` and you have provided
this: :file:`yourapplication/admin/templates/admin/index.html`. The reason
for the extra ``admin`` folder is to avoid getting our template overridden
by a template named ``index.html`` in the actual application template
folder.
folder.
To further reiterate this: if you have a blueprint named ``admin`` and you
want to render a template called :file:`index.html` which is specific to this
@ -245,4 +245,22 @@ Here is an example for a "404 Page Not Found" exception::
def page_not_found(e):
return render_template('pages/404.html')
Most errorhandlers will simply work as expected; however, there is a caveat
concerning handlers for 404 and 405 exceptions. These errorhandlers are only
invoked from an appropriate ``raise`` statement or a call to ``abort`` in another
of the blueprint's view functions; they are not invoked by, e.g., an invalid URL
access. This is because the blueprint does not "own" a certain URL space, so
the application instance has no way of knowing which blueprint errorhandler it
should run if given an invalid URL. If you would like to execute different
handling strategies for these errors based on URL prefixes, they may be defined
at the application level using the ``request`` proxy object::
@app.errorhandler(404)
@app.errorhandler(405)
def _handle_api_error(ex):
if request.path.startswith('/api/'):
return jsonify_error(ex)
else:
return ex
More information on error handling see :ref:`errorpages`.

View file

@ -56,6 +56,18 @@ If you are constantly working with a virtualenv you can also put the
bottom of the file. That way every time you activate your virtualenv you
automatically also activate the correct application name.
Edit the activate script for the shell you use. For example:
Unix Bash: ``venv/bin/activate``::
FLASK_APP=hello
export FLASK_APP
Windows CMD.exe: ``venv\Scripts\activate.bat``::
set "FLASK_APP=hello"
:END
Debug Flag
----------
@ -139,8 +151,8 @@ This could be a file named :file:`autoapp.py` with these contents::
from yourapplication import create_app
app = create_app(os.environ['YOURAPPLICATION_CONFIG'])
Once this has happened you can make the flask command automatically pick
it up::
Once this has happened you can make the :command:`flask` command automatically
pick it up::
export YOURAPPLICATION_CONFIG=/path/to/config.cfg
export FLASK_APP=/path/to/autoapp.py

View file

@ -11,10 +11,13 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
from __future__ import print_function
from datetime import datetime
import os
import sys
import pkg_resources
import time
import datetime
BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@ -35,6 +38,14 @@ extensions = [
'flaskdocext'
]
try:
__import__('sphinxcontrib.log_cabinet')
except ImportError:
print('sphinxcontrib-log-cabinet is not installed.')
print('Changelog directives will not be re-organized.')
else:
extensions.append('sphinxcontrib.log_cabinet')
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -49,7 +60,7 @@ master_doc = 'index'
# General information about the project.
project = u'Flask'
copyright = u'2010 - {0}, Armin Ronacher'.format(datetime.utcnow().year)
copyright = u'2010 - {0}, Armin Ronacher'.format(BUILD_DATE.year)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -231,7 +242,7 @@ latex_additional_files = ['flaskstyle.sty', 'logo.pdf']
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# The unique identifier of the text. This can be an ISBN number
# or the project homepage.
#epub_identifier = ''
@ -257,7 +268,7 @@ intersphinx_mapping = {
'werkzeug': ('http://werkzeug.pocoo.org/docs/', None),
'click': ('http://click.pocoo.org/', None),
'jinja': ('http://jinja.pocoo.org/docs/', None),
'sqlalchemy': ('http://docs.sqlalchemy.org/en/latest/', None),
'sqlalchemy': ('https://docs.sqlalchemy.org/en/latest/', None),
'wtforms': ('https://wtforms.readthedocs.io/en/latest/', None),
'blinker': ('https://pythonhosted.org/blinker/', None)
}

View file

@ -44,6 +44,21 @@ method::
SECRET_KEY='...'
)
.. admonition:: Debug Mode with the ``flask`` Script
If you use the :command:`flask` script to start a local development
server, to enable the debug mode, you need to export the ``FLASK_DEBUG``
environment variable before running the server::
$ export FLASK_DEBUG=1
$ flask run
(On Windows you need to use ``set`` instead of ``export``).
``app.debug`` and ``app.config['DEBUG']`` are not compatible with
  the :command:`flask` script. They only worked when using ``Flask.run()``
method.
Builtin Configuration Values
----------------------------
@ -52,7 +67,8 @@ The following configuration values are used internally by Flask:
.. tabularcolumns:: |p{6.5cm}|p{8.5cm}|
================================= =========================================
``DEBUG`` enable/disable debug mode
``DEBUG`` enable/disable debug mode when using
``Flask.run()`` method to start server
``TESTING`` enable/disable testing mode
``PROPAGATE_EXCEPTIONS`` explicitly enable or disable the
propagation of exceptions. If not set or
@ -116,13 +132,13 @@ The following configuration values are used internally by Flask:
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
is configured to live. This is for
session cookie as path value. If
domains are used, this should be
``None``.
``APPLICATION_ROOT`` The path value used for the session
cookie if ``SESSION_COOKIE_PATH`` isn't
set. If it's also ``None`` ``'/'`` is used.
Note that to actually serve your Flask
app under a subpath you need to tell
your WSGI container the ``SCRIPT_NAME``
WSGI environment variable.
``MAX_CONTENT_LENGTH`` If set to a value in bytes, Flask will
reject incoming requests with a
content length greater than this by
@ -178,11 +194,9 @@ The following configuration values are used internally by Flask:
This is not recommended but might give
you a performance improvement on the
cost of cacheability.
``JSONIFY_PRETTYPRINT_REGULAR`` If this is set to ``True`` (the default)
jsonify responses will be pretty printed
if they are not requested by an
XMLHttpRequest object (controlled by
the ``X-Requested-With`` header)
``JSONIFY_PRETTYPRINT_REGULAR`` If this is set to ``True`` or the Flask app
is running in debug mode, jsonify responses
will be pretty printed.
``JSONIFY_MIMETYPE`` MIME type used for jsonify responses.
``TEMPLATES_AUTO_RELOAD`` Whether to check for modifications of
the template source and reload it
@ -262,7 +276,7 @@ So a common pattern is this::
This first loads the configuration from the
`yourapplication.default_settings` module and then overrides the values
with the contents of the file the :envvar:``YOURAPPLICATION_SETTINGS``
with the contents of the file the :envvar:`YOURAPPLICATION_SETTINGS`
environment variable points to. This environment variable can be set on
Linux or OS X with the export command in the shell before starting the
server::

View file

@ -144,7 +144,7 @@ A basic FastCGI configuration for lighttpd looks like that::
)
alias.url = (
"/static/" => "/path/to/your/static"
"/static/" => "/path/to/your/static/"
)
url.rewrite-once = (
@ -159,7 +159,7 @@ work in the URL root you have to work around a lighttpd bug with the
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/projects/lighttpd/wiki/Docs_ModFastCGI>`_ (note that
<https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModFastCGI>`_ (note that
explicitly passing a socket to run() is no longer necessary).
Configuring nginx
@ -234,7 +234,7 @@ python path. Common problems are:
web server.
- Different python interpreters being used.
.. _nginx: http://nginx.org/
.. _lighttpd: http://www.lighttpd.net/
.. _nginx: https://nginx.org/
.. _lighttpd: https://www.lighttpd.net/
.. _cherokee: http://cherokee-project.com/
.. _flup: https://pypi.python.org/pypi/flup

View file

@ -21,8 +21,10 @@ Hosted options
- `Deploying Flask on OpenShift <https://developers.openshift.com/en/python-flask.html>`_
- `Deploying Flask on Webfaction <http://flask.pocoo.org/snippets/65/>`_
- `Deploying Flask on Google App Engine <https://github.com/kamalgill/flask-appengine-template>`_
- `Deploying Flask on AWS Elastic Beanstalk <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html>`_
- `Sharing your Localhost Server with Localtunnel <http://flask.pocoo.org/snippets/89/>`_
- `Deploying on Azure (IIS) <https://azure.microsoft.com/documentation/articles/web-sites-python-configure/>`_
- `Deploying on PythonAnywhere <https://help.pythonanywhere.com/pages/Flask/>`_
Self-hosted options
-------------------

View file

@ -13,7 +13,7 @@ If you are using the `Apache`_ webserver, consider using `mod_wsgi`_.
not called because this will always start a local WSGI server which
we do not want if we deploy that application to mod_wsgi.
.. _Apache: http://httpd.apache.org/
.. _Apache: https://httpd.apache.org/
Installing `mod_wsgi`
---------------------
@ -114,7 +114,7 @@ refuse to run with the above configuration. On a Windows system, eliminate those
Note: There have been some changes in access control configuration for `Apache 2.4`_.
.. _Apache 2.4: http://httpd.apache.org/docs/trunk/upgrading.html
.. _Apache 2.4: https://httpd.apache.org/docs/trunk/upgrading.html
Most notably, the syntax for directory permissions has changed from httpd 2.2
@ -133,9 +133,9 @@ to httpd 2.4 syntax
For more information consult the `mod_wsgi documentation`_.
.. _mod_wsgi: https://github.com/GrahamDumpleton/mod_wsgi
.. _installation instructions: http://modwsgi.readthedocs.io/en/develop/installation.html
.. _installation instructions: https://modwsgi.readthedocs.io/en/develop/installation.html
.. _virtual python: https://pypi.python.org/pypi/virtualenv
.. _mod_wsgi documentation: http://modwsgi.readthedocs.io/en/develop/index.html
.. _mod_wsgi documentation: https://modwsgi.readthedocs.io/en/develop/index.html
Troubleshooting
---------------

View file

@ -66,7 +66,7 @@ to have it in the URL root its a bit simpler::
uwsgi_pass unix:/tmp/yourapplication.sock;
}
.. _nginx: http://nginx.org/
.. _lighttpd: http://www.lighttpd.net/
.. _nginx: https://nginx.org/
.. _lighttpd: https://www.lighttpd.net/
.. _cherokee: http://cherokee-project.com/
.. _uwsgi: http://projects.unbit.it/uwsgi/

View file

@ -34,7 +34,7 @@ Error Logging Tools
Sending error mails, even if just for critical ones, can become
overwhelming if enough users are hitting the error and log files are
typically never looked at. This is why we recommend using `Sentry
<http://www.getsentry.com/>`_ for dealing with application errors. It's
<https://www.getsentry.com/>`_ for dealing with application errors. It's
available as an Open Source project `on GitHub
<https://github.com/getsentry/sentry>`__ and is also available as a `hosted version
<https://getsentry.com/signup/>`_ which you can try for free. Sentry
@ -89,7 +89,7 @@ Register error handlers using :meth:`~flask.Flask.errorhandler` or
@app.errorhandler(werkzeug.exceptions.BadRequest)
def handle_bad_request(e):
return 'bad request!'
app.register_error_handler(400, lambda e: 'bad request!')
Those two ways are equivalent, but the first one is more clear and leaves
@ -216,7 +216,7 @@ A formatter can be instantiated with a format string. Note that
tracebacks are appended to the log entry automatically. You don't have to
do that in the log formatter format string.
Here some example setups:
Here are some example setups:
Email
`````
@ -276,8 +276,9 @@ that this list is not complete, consult the official documentation of the
| ``%(lineno)d`` | Source line number where the logging call was |
| | issued (if available). |
+------------------+----------------------------------------------------+
| ``%(asctime)s`` | Human-readable time when the LogRecord` was |
| | created. By default this is of the form |
| ``%(asctime)s`` | Human-readable time when the |
| | :class:`~logging.LogRecord` was created. |
| | By default this is of the form |
| | ``"2003-07-08 16:49:45,896"`` (the numbers after |
| | the comma are millisecond portion of the time). |
| | This can be changed by subclassing the formatter |

View file

@ -29,12 +29,6 @@ be something like "Flask-SimpleXML". Make sure to include the name
This is how users can then register dependencies to your extension in
their :file:`setup.py` files.
Flask sets up a redirect package called :data:`flask.ext` where users
should import the extensions from. If you for instance have a package
called ``flask_something`` users would import it as
``flask.ext.something``. This is done to transition from the old
namespace packages. See :ref:`ext-import-transition` for more details.
But what do extensions look like themselves? An extension has to ensure
that it works with multiple Flask application instances at once. This is
a requirement because many people will use patterns like the
@ -393,8 +387,6 @@ extension to be approved you have to follow these guidelines:
Python 2.7
.. _ext-import-transition:
Extension Import Transition
---------------------------
@ -413,6 +405,6 @@ schema. The ``flask.ext.foo`` compatibility alias is still in Flask 0.11 but is
now deprecated -- you should use ``flask_foo``.
.. _OAuth extension: http://pythonhosted.org/Flask-OAuth/
.. _OAuth extension: https://pythonhosted.org/Flask-OAuth/
.. _mailinglist: http://flask.pocoo.org/mailinglist/
.. _IRC channel: http://flask.pocoo.org/community/irc/

View file

@ -3,163 +3,173 @@
Installation
============
Flask depends on some external libraries, like `Werkzeug
<http://werkzeug.pocoo.org/>`_ and `Jinja2 <http://jinja.pocoo.org/>`_.
Werkzeug is a toolkit for WSGI, the standard Python interface between web
applications and a variety of servers for both development and deployment.
Jinja2 renders templates.
Python Version
--------------
So how do you get all that on your computer quickly? There are many ways you
could do that, but the most kick-ass method is virtualenv, so let's have a look
at that first.
We recommend using the latest version of Python 3. Flask supports Python 3.3
and newer, Python 2.6 and newer, and PyPy.
You will need Python 2.6 or newer to get started, so be sure to have an
up-to-date Python 2.x installation. For using Flask with Python 3 have a
look at :ref:`python3-support`.
Dependencies
------------
.. _virtualenv:
These distributions will be installed automatically when installing Flask.
virtualenv
----------
* `Werkzeug`_ implements WSGI, the standard Python interface between
applications and servers.
* `Jinja`_ is a template language that renders the pages your application
serves.
* `MarkupSafe`_ comes with Jinja. It escapes untrusted input when rendering
templates to avoid injection attacks.
* `ItsDangerous`_ securely signs data to ensure its integrity. This is used
to protect Flask's session cookie.
* `Click`_ is a framework for writing command line applications. It provides
the ``flask`` command and allows adding custom management commands.
Virtualenv is probably what you want to use during development, and if you have
shell access to your production machines, you'll probably want to use it there,
too.
.. _Werkzeug: http://werkzeug.pocoo.org/
.. _Jinja: http://jinja.pocoo.org/
.. _MarkupSafe: https://pypi.python.org/pypi/MarkupSafe
.. _ItsDangerous: https://pythonhosted.org/itsdangerous/
.. _Click: http://click.pocoo.org/
What problem does virtualenv solve? If you like Python as much as I do,
chances are you want to use it for other projects besides Flask-based web
applications. But the more projects you have, the more likely it is that you
will be working with different versions of Python itself, or at least different
versions of Python libraries. Let's face it: quite often libraries break
backwards compatibility, and it's unlikely that any serious application will
have zero dependencies. So what do you do if two or more of your projects have
conflicting dependencies?
Optional dependencies
~~~~~~~~~~~~~~~~~~~~~
Virtualenv to the rescue! Virtualenv enables multiple side-by-side
installations of Python, one for each project. It doesn't actually install
separate copies of Python, but it does provide a clever way to keep different
project environments isolated. Let's see how virtualenv works.
These distributions will not be installed automatically. Flask will detect and
use them if you install them.
If you are on Mac OS X or Linux, chances are that the following
command will work for you::
* `Blinker`_ provides support for :ref:`signals`.
* `SimpleJSON`_ is a fast JSON implementation that is compatible with
Python's ``json`` module. It is preferred for JSON operations if it is
installed.
$ sudo pip install virtualenv
.. _Blinker: https://pythonhosted.org/blinker/
.. _SimpleJSON: https://simplejson.readthedocs.io/
It will probably install virtualenv on your system. Maybe it's even
in your package manager. If you use Ubuntu, try::
Virtual environments
--------------------
$ sudo apt-get install python-virtualenv
Use a virtual environment to manage the dependencies for your project, both in
development and in production.
If you are on Windows and don't have the ``easy_install`` command, you must
install it first. Check the :ref:`windows-easy-install` section for more
information about how to do that. Once you have it installed, run the same
commands as above, but without the ``sudo`` prefix.
What problem does a virtual environment solve? The more Python projects you
have, the more likely it is that you need to work with different versions of
Python libraries, or even Python itself. Newer versions of libraries for one
project can break compatibility in another project.
Once you have virtualenv installed, just fire up a shell and create
your own environment. I usually create a project folder and a :file:`venv`
folder within::
Virtual environments are independent groups of Python libraries, one for each
project. Packages installed for one project will not affect other projects or
the operating system's packages.
$ mkdir myproject
$ cd myproject
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip............done.
Python 3 comes bundled with the :mod:`venv` module to create virtual
environments. If you're using a modern version of Python, you can continue on
to the next section.
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::
If you're using Python 2, see :ref:`install-install-virtualenv` first.
$ . venv/bin/activate
.. _install-create-env:
If you are a Windows user, the following command is for you::
Create an environment
~~~~~~~~~~~~~~~~~~~~~
$ venv\scripts\activate
Create a project folder and a :file:`venv` folder within:
Either way, you should now be using your virtualenv (notice how the prompt of
your shell has changed to show the active environment).
.. code-block:: sh
And if you want to go back to the real world, use the following command::
mkdir myproject
cd myproject
python3 -m venv venv
$ deactivate
On Windows:
After doing this, the prompt of your shell should be as familiar as before.
.. code-block:: bat
Now, let's move on. Enter the following command to get Flask activated in your
virtualenv::
py -3 -m venv venv
$ pip install Flask
If you needed to install virtualenv because you are on an older version of
Python, use the following command instead:
A few seconds later and you are good to go.
.. code-block:: sh
virtualenv venv
System-Wide Installation
------------------------
On Windows:
This is possible as well, though I do not recommend it. Just run
``pip`` with root privileges::
.. code-block:: bat
$ sudo pip install Flask
\Python27\Scripts\virtualenv.exe venv
(On Windows systems, run it in a command-prompt window with administrator
privileges, and leave out ``sudo``.)
Activate the environment
~~~~~~~~~~~~~~~~~~~~~~~~
Before you work on your project, activate the corresponding environment:
Living on the Edge
.. code-block:: sh
. venv/bin/activate
On Windows:
.. code-block:: bat
venv\Scripts\activate
Your shell prompt will change to show the name of the activated environment.
Install Flask
-------------
Within the activated environment, use the following command to install Flask:
.. code-block:: sh
pip install Flask
Living on the edge
~~~~~~~~~~~~~~~~~~
If you want to work with the latest Flask code before it's released, install or
update the code from the master branch:
.. code-block:: sh
pip install -U https://github.com/pallets/flask/archive/master.tar.gz
.. _install-install-virtualenv:
Install virtualenv
------------------
If you want to work with the latest version of Flask, there are two ways: you
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.
If you are using Python 2, the venv module is not available. Instead,
install `virtualenv`_.
Get the git checkout in a new virtualenv and run in development mode::
On Linux, virtualenv is provided by your package manager:
$ git clone http://github.com/pallets/flask.git
Initialized empty Git repository in ~/dev/flask/.git/
$ cd flask
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip............done.
$ . venv/bin/activate
$ python setup.py develop
...
Finished processing dependencies for Flask
.. code-block:: sh
This will pull in the dependencies and activate the git head as the current
version inside the virtualenv. Then all you have to do is run ``git pull
origin`` to update to the latest version.
# Debian, Ubuntu
sudo apt-get install python-virtualenv
.. _windows-easy-install:
# CentOS, Fedora
sudo yum install python-virtualenv
`pip` and `setuptools` on Windows
---------------------------------
# Arch
sudo pacman -S python-virtualenv
Sometimes getting the standard "Python packaging tools" like ``pip``, ``setuptools``
and ``virtualenv`` can be a little trickier, but nothing very hard. The crucial
package you will need is pip - this will let you install
anything else (like virtualenv). Fortunately there is a "bootstrap script"
you can run to install.
If you are on Mac OS X or Windows, download `get-pip.py`_, then:
If you don't currently have ``pip``, then `get-pip.py` will install it for you.
.. code-block:: sh
`get-pip.py`_
sudo python2 Downloads/get-pip.py
sudo python2 -m pip install virtualenv
It should be double-clickable once you download it. If you already have ``pip``,
you can upgrade them by running::
On Windows, as an administrator:
> pip install --upgrade pip setuptools
.. code-block:: bat
Most often, once you pull up a command prompt you want to be able to type ``pip``
and ``python`` which will run those things, but this might not automatically happen
on Windows, because it doesn't know where those executables are (give either a try!).
\Python27\python.exe Downloads\get-pip.py
\Python27\python.exe -m pip install virtualenv
To fix this, you should be able to navigate to your Python install directory
(e.g :file:`C:\Python27`), then go to :file:`Tools`, then :file:`Scripts`, then find the
:file:`win_add2path.py` file and run that. Open a **new** Command Prompt and
check that you can now just type ``python`` to bring up the interpreter.
Finally, to install `virtualenv`_, you can simply run::
> pip install virtualenv
Then you can be off on your way following the installation instructions above.
Now you can continue to :ref:`install-create-env`.
.. _virtualenv: https://virtualenv.pypa.io/
.. _get-pip.py: https://bootstrap.pypa.io/get-pip.py

View file

@ -6,7 +6,7 @@ Application Factories
If you are already using packages and blueprints for your application
(:ref:`blueprints`) there are a couple of really nice ways to further improve
the experience. A common pattern is creating the application object when
the blueprint is imported. But if you move the creation of this object,
the blueprint is imported. But if you move the creation of this object
into a function, you can then create multiple instances of this app later.
So why would you want to do this?
@ -60,7 +60,7 @@ Factories & Extensions
It's preferable to create your extensions and app factories so that the
extension object does not initially get bound to the application.
Using `Flask-SQLAlchemy <http://pythonhosted.org/Flask-SQLAlchemy/>`_,
Using `Flask-SQLAlchemy <http://flask-sqlalchemy.pocoo.org/>`_,
as an example, you should not do something along those lines::
def create_app(config_filename):

View file

@ -3,71 +3,43 @@
Deferred Request Callbacks
==========================
One of the design principles of Flask is that response objects are created
and passed down a chain of potential callbacks that can modify them or
replace them. When the request handling starts, there is no response
object yet. It is created as necessary either by a view function or by
some other component in the system.
One of the design principles of Flask is that response objects are created and
passed down a chain of potential callbacks that can modify them or replace
them. When the request handling starts, there is no response object yet. It is
created as necessary either by a view function or by some other component in
the system.
But what happens if you want to modify the response at a point where the
response does not exist yet? A common example for that would be a
before-request function that wants to set a cookie on the response object.
What happens if you want to modify the response at a point where the response
does not exist yet? A common example for that would be a
:meth:`~flask.Flask.before_request` callback that wants to set a cookie on the
response object.
One way is to avoid the situation. Very often that is possible. For
instance you can try to move that logic into an after-request callback
instead. Sometimes however moving that code there is just not a very
pleasant experience or makes code look very awkward.
One way is to avoid the situation. Very often that is possible. For instance
you can try to move that logic into a :meth:`~flask.Flask.after_request`
callback instead. However, sometimes moving code there makes it more
more complicated or awkward to reason about.
As an alternative possibility you can attach a bunch of callback functions
to the :data:`~flask.g` object and call them at the end of the request.
This way you can defer code execution from anywhere in the application.
The Decorator
-------------
The following decorator is the key. It registers a function on a list on
the :data:`~flask.g` object::
from flask import g
def after_this_request(f):
if not hasattr(g, 'after_request_callbacks'):
g.after_request_callbacks = []
g.after_request_callbacks.append(f)
return f
Calling the Deferred
--------------------
Now you can use the `after_this_request` decorator to mark a function to
be called at the end of the request. But we still need to call them. For
this the following function needs to be registered as
:meth:`~flask.Flask.after_request` callback::
@app.after_request
def call_after_request_callbacks(response):
for callback in getattr(g, 'after_request_callbacks', ()):
callback(response)
return response
A Practical Example
-------------------
As an alternative, you can use :func:`~flask.after_this_request` to register
callbacks that will execute after only the current request. This way you can
defer code execution from anywhere in the application, based on the current
request.
At any time during a request, we can register a function to be called at the
end of the request. For example you can remember the current language of the
user in a cookie in the before-request function::
end of the request. For example you can remember the current language of the
user in a cookie in a :meth:`~flask.Flask.before_request` callback::
from flask import request
from flask import request, after_this_request
@app.before_request
def detect_user_language():
language = request.cookies.get('user_lang')
if language is None:
language = guess_language_from_request()
# when the response exists, set a cookie with the language
@after_this_request
def remember_language(response):
response.set_cookie('user_lang', language)
g.language = language

View file

@ -174,4 +174,4 @@ the code without having to run ``install`` again after each change.
.. _pip: https://pypi.python.org/pypi/pip
.. _Setuptools: https://pythonhosted.org/setuptools
.. _Setuptools: https://pypi.python.org/pypi/setuptools

View file

@ -47,37 +47,53 @@ even if the application behaves correctly:
Error Handlers
--------------
An error handler is a function, just like a view function, but it is
called when an error happens and is passed that error. The error is most
likely a :exc:`~werkzeug.exceptions.HTTPException`, but in one case it
can be a different error: a handler for internal server errors will be
passed other exception instances as well if they are uncaught.
An error handler is a function that returns a response when a type of error is
raised, similar to how a view is a function that returns a response when a
request URL is matched. It is passed the instance of the error being handled,
which is most likely a :exc:`~werkzeug.exceptions.HTTPException`. An error
handler for "500 Internal Server Error" will be passed uncaught exceptions in
addition to explicit 500 errors.
An error handler is registered with the :meth:`~flask.Flask.errorhandler`
decorator and the error code of the exception. Keep in mind that Flask
will *not* set the error code for you, so make sure to also provide the
HTTP status code when returning a response.
decorator or the :meth:`~flask.Flask.register_error_handler` method. A handler
can be registered for a status code, like 404, or for an exception class.
Please note that if you add an error handler for "500 Internal Server
Error", Flask will not trigger it if it's running in Debug mode.
The status code of the response will not be set to the handler's code. Make
sure to provide the appropriate HTTP status code when returning a response from
a handler.
Here an example implementation for a "404 Page Not Found" exception::
A handler for "500 Internal Server Error" will not be used when running in
debug mode. Instead, the interactive debugger will be shown.
Here is an example implementation for a "404 Page Not Found" exception::
from flask import render_template
@app.errorhandler(404)
def page_not_found(e):
# note that we set the 404 status explicitly
return render_template('404.html'), 404
When using the :ref:`application factory pattern <app-factories>`::
from flask import Flask, render_template
def page_not_found(e):
return render_template('404.html'), 404
def create_app(config_filename):
app = Flask(__name__)
app.register_error_handler(404, page_not_found)
return app
An example template might be this:
.. sourcecode:: html+jinja
{% extends "layout.html" %}
{% block title %}Page Not Found{% endblock %}
{% block body %}
<h1>Page Not Found</h1>
<p>What you were looking for is just not there.
<p><a href="{{ url_for('index') }}">go somewhere nice</a>
{% endblock %}
{% extends "layout.html" %}
{% block title %}Page Not Found{% endblock %}
{% block body %}
<h1>Page Not Found</h1>
<p>What you were looking for is just not there.
<p><a href="{{ url_for('index') }}">go somewhere nice</a>
{% endblock %}

View file

@ -49,5 +49,5 @@ web server's documentation.
See also
--------
* The `Favicon <http://en.wikipedia.org/wiki/Favicon>`_ article on
* The `Favicon <https://en.wikipedia.org/wiki/Favicon>`_ article on
Wikipedia

View file

@ -21,7 +21,7 @@ specific upload folder and displays a file to the user. Let's look at the
bootstrapping code for our application::
import os
from flask import Flask, request, redirect, url_for
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
@ -58,7 +58,7 @@ the file and redirects the user to the URL for the uploaded file::
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
@ -72,8 +72,8 @@ the file and redirects the user to the URL for the uploaded file::
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
@ -181,4 +181,4 @@ applications dealing with uploads, there is also a Flask extension called
blacklisting of extensions and more.
.. _jQuery: https://jquery.com/
.. _Flask-Uploads: http://pythonhosted.org/Flask-Uploads/
.. _Flask-Uploads: https://pythonhosted.org/Flask-Uploads/

View file

@ -17,6 +17,10 @@ this::
login.html
...
If you find yourself stuck on something, feel free
to take a look at the source code for this example.
You'll find `the full src for this example here`_.
Simple Packages
---------------
@ -61,7 +65,7 @@ that tells Flask where to find the application instance::
export FLASK_APP=yourapplication
If you are outside of the project directory make sure to provide the exact
path to your application directory. Similiarly you can turn on "debug
path to your application directory. Similarly you can turn on "debug
mode" with this environment variable::
export FLASK_DEBUG=true
@ -130,6 +134,7 @@ You should then end up with something like that::
.. _working-with-modules:
.. _the full src for this example here: https://github.com/pallets/flask/tree/master/examples/patterns/largerapp
Working with Blueprints
-----------------------

View file

@ -22,7 +22,7 @@ if you want to get started quickly.
You can download `Flask-SQLAlchemy`_ from `PyPI
<https://pypi.python.org/pypi/Flask-SQLAlchemy>`_.
.. _Flask-SQLAlchemy: http://pythonhosted.org/Flask-SQLAlchemy/
.. _Flask-SQLAlchemy: http://flask-sqlalchemy.pocoo.org/
Declarative
@ -108,9 +108,9 @@ Querying is simple as well:
>>> User.query.filter(User.name == 'admin').first()
<User u'admin'>
.. _SQLAlchemy: http://www.sqlalchemy.org/
.. _SQLAlchemy: https://www.sqlalchemy.org/
.. _declarative:
http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/
https://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/
Manual Object Relational Mapping
--------------------------------
@ -135,7 +135,7 @@ Here is an example :file:`database.py` module for your application::
def init_db():
metadata.create_all(bind=engine)
As for the declarative approach you need to close the session after
As in the declarative approach, you need to close the session after
each request or application context shutdown. Put this into your
application module::
@ -215,4 +215,4 @@ You can also pass strings of SQL statements to the
(1, u'admin', u'admin@localhost')
For more information about SQLAlchemy, head over to the
`website <http://www.sqlalchemy.org/>`_.
`website <https://www.sqlalchemy.org/>`_.

View file

@ -3,8 +3,8 @@
Using SQLite 3 with Flask
=========================
In Flask you can easily implement the opening of database connections on
demand and closing them when the context dies (usually at the end of the
In Flask you can easily implement the opening of database connections on
demand and closing them when the context dies (usually at the end of the
request).
Here is a simple example of how you can use SQLite 3 with Flask::
@ -71,7 +71,7 @@ Now in each request handling function you can access `g.db` to get the
current open database connection. To simplify working with SQLite, a
row factory function is useful. It is executed for every result returned
from the database to convert the result. For instance, in order to get
dictionaries instead of tuples, this could be inserted into the ``get_db``
dictionaries instead of tuples, this could be inserted into the ``get_db``
function we created above::
def make_dicts(cursor, row):
@ -102,15 +102,15 @@ This would use Row objects rather than dicts to return the results of queries. T
Additionally, it is a good idea to provide a query function that combines
getting the cursor, executing and fetching the results::
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
This handy little function, in combination with a row factory, makes
working with the database much more pleasant than it is by just using the
This handy little function, in combination with a row factory, makes
working with the database much more pleasant than it is by just using the
raw cursor and connection objects.
Here is how you can use it::
@ -131,7 +131,7 @@ To pass variable parts to the SQL statement, use a question mark in the
statement and pass in the arguments as a list. Never directly add them to
the SQL statement with string formatting because this makes it possible
to attack the application using `SQL Injections
<http://en.wikipedia.org/wiki/SQL_injection>`_.
<https://en.wikipedia.org/wiki/SQL_injection>`_.
Initial Schemas
---------------

View file

@ -19,7 +19,7 @@ forms.
fun. You can get it from `PyPI
<https://pypi.python.org/pypi/Flask-WTF>`_.
.. _Flask-WTF: http://pythonhosted.org/Flask-WTF/
.. _Flask-WTF: https://flask-wtf.readthedocs.io/en/stable/
The Forms
---------

View file

@ -102,9 +102,9 @@ docs to see the alternative method for running a server.
Invalid Import Name
```````````````````
The ``FLASK_APP`` environment variable is the name of the module to import at
:command:`flask run`. In case that module is incorrectly named you will get an
import error upon start (or if debug is enabled when you navigate to the
The ``FLASK_APP`` environment variable is the name of the module to import at
:command:`flask run`. In case that module is incorrectly named you will get an
import error upon start (or if debug is enabled when you navigate to the
application). It will tell you what it tried to import and why it failed.
The most common reason is a typo or because you did not actually create an
@ -159,14 +159,11 @@ Have another debugger in mind? See :ref:`working-with-debuggers`.
Routing
-------
Modern web applications have beautiful URLs. This helps people remember
the URLs, which is especially handy for applications that are used from
mobile devices with slower network connections. If the user can directly
go to the desired page without having to hit the index page it is more
likely they will like the page and come back next time.
Modern web applications use meaningful URLs to help users. Users are more
likely to like a page and come back if the page uses a meaningful URL they can
remember and use to directly visit a page.
As you have seen above, the :meth:`~flask.Flask.route` decorator is used to
bind a function to a URL. Here are some basic examples::
Use the :meth:`~flask.Flask.route` decorator to bind a function to a URL. ::
@app.route('/')
def index():
@ -176,16 +173,16 @@ bind a function to a URL. Here are some basic examples::
def hello():
return 'Hello, World'
But there is more to it! You can make certain parts of the URL dynamic and
attach multiple rules to a function.
You can do more! You can make parts of the URL dynamic and attach multiple
rules to a function.
Variable Rules
``````````````
To add variable parts to a URL you can mark these special sections as
``<variable_name>``. Such a part is then passed as a keyword argument to your
function. Optionally a converter can be used by specifying a rule with
``<converter:variable_name>``. Here are some nice examples::
You can add variable sections to a URL by marking sections with
``<variable_name>``. Your function then receives the ``<variable_name>``
as a keyword argument. Optionally, you can use a converter to specify the type
of the argument like ``<converter:variable_name>``. ::
@app.route('/user/<username>')
def show_user_profile(username):
@ -197,111 +194,111 @@ function. Optionally a converter can be used by specifying a rule with
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
The following converters exist:
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return 'Subpath %s' % subpath
=========== ===============================================
`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
`any` matches one of the items provided
`uuid` accepts UUID strings
=========== ===============================================
Converter types:
.. admonition:: Unique URLs / Redirection Behavior
========== ==========================================
``string`` (default) accepts any text without a slash
``int`` accepts positive integers
``float`` accepts positive floating point values
``path`` like ``string`` but also accepts slashes
``uuid`` accepts UUID strings
========== ==========================================
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.
Unique URLs / Redirection Behavior
``````````````````````````````````
Take these two rules::
Take these two rules::
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
@app.route('/about')
def about():
return 'The about page'
Though they look rather similar, they differ in their use of the trailing
slash in the URL *definition*. In the first case, the canonical URL for the
``projects`` endpoint has a trailing slash. In that sense, it is similar to
a folder on a filesystem. Accessing it without a trailing slash will cause
Flask to redirect to the canonical URL with the trailing slash.
Though they look similar, they differ in their use of the trailing slash in
the URL. In the first case, the canonical URL for the ``projects`` endpoint
uses a trailing slash. It's similar to a folder in a file system; if you
access the URL without a trailing slash, Flask redirects you to the
canonical URL with the trailing slash.
In the second case, however, the URL is defined without a trailing slash,
rather like the pathname of a file on UNIX-like systems. Accessing the URL
with a trailing slash will produce a 404 "Not Found" error.
This behavior allows relative URLs to continue working even if the trailing
slash is omitted, consistent with how Apache and other servers work. Also,
the URLs will stay unique, which helps search engines avoid indexing the
same page twice.
In the second case, however, the URL definition lacks a trailing slash,
like the pathname of a file on UNIX-like systems. Accessing the URL with a
trailing slash produces a 404 “Not Found” error.
This behavior allows relative URLs to continue working even if the trailing
slash is omitted, consistent with how Apache and other servers work. Also,
the URLs will stay unique, which helps search engines avoid indexing the
same page twice.
.. _url-building:
URL Building
````````````
If it can match URLs, can Flask also generate them? Of course it can. To
build a URL to a specific function you can use the :func:`~flask.url_for`
function. It accepts the name of the function as first argument and a number
of keyword arguments, each corresponding to the variable part of the URL rule.
Unknown variable parts are appended to the URL as query parameters. Here are
some examples::
To build a URL to a specific function, use the :func:`~flask.url_for` function.
It accepts the name of the function as its first argument and any number of
keyword arguments, each corresponding to a variable part of the URL rule.
Unknown variable parts are appended to the URL as query parameters.
Why would you want to build URLs using the URL reversing function
:func:`~flask.url_for` instead of hard-coding them into your templates?
1. Reversing is often more descriptive than hard-coding the URLs.
2. You can change your URLs in one go instead of needing to remember to
manually change hard-coded URLs.
3. URL building handles escaping of special characters and Unicode data
transparently.
4. If your application is placed outside the URL root, for example, in
``/myapplication`` instead of ``/``, :func:`~flask.url_for` properly
handles that for you.
For example, here we use the :meth:`~flask.Flask.test_request_context` method
to try out :func:`~flask.url_for`. :meth:`~flask.Flask.test_request_context`
tells Flask to behave as though it's handling a request even while we use a
Python shell. See :ref:`context-locals`. ::
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/login')
def login():
return 'login'
@app.route('/user/<username>')
def profile(username):
return '{}'s profile'.format(username)
with app.test_request_context():
print(url_for('index'))
print(url_for('login'))
print(url_for('login', next='/'))
print(url_for('profile', username='John Doe'))
>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
... print url_for('index')
... print url_for('login')
... print url_for('login', next='/')
... print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe
(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 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 using the URL reversing function
:func:`~flask.url_for` instead of hard-coding them into your templates?
There are three good reasons for this:
1. Reversing is often more descriptive than hard-coding the URLs. More
importantly, it allows you to change URLs in one go, without having to
remember to change URLs all over the place.
2. URL building will handle escaping of special characters and Unicode
data transparently for you, so you don't have to deal with them.
3. If your application is placed outside the URL root - say, in
``/myapplication`` instead of ``/`` - :func:`~flask.url_for` will handle
that properly for you.
HTTP Methods
````````````
HTTP (the protocol web applications are speaking) knows different methods for
accessing URLs. By default, a route only answers to ``GET`` requests, but that
can be changed by providing the ``methods`` argument to the
:meth:`~flask.Flask.route` decorator. Here are some examples::
from flask import request
Web applications use different HTTP methods when accessing URLs. You should
familiarize yourself with the HTTP methods as you work with Flask. By default,
a route only answers to ``GET`` requests. You can use the ``methods`` argument
of the :meth:`~flask.Flask.route` decorator to handle different HTTP methods.
::
@app.route('/login', methods=['GET', 'POST'])
def login():
@ -310,64 +307,11 @@ can be changed by providing the ``methods`` argument to the
else:
show_the_login_form()
If ``GET`` is present, ``HEAD`` will be added automatically for you. You
don't have to deal with that. It will also make sure that ``HEAD`` requests
are handled as the `HTTP RFC`_ (the document describing the HTTP
protocol) demands, so you can completely ignore that part of the HTTP
specification. Likewise, as of Flask 0.6, ``OPTIONS`` is implemented for you
automatically as well.
If ``GET`` is present, Flask automatically adds support for the ``HEAD`` method
and handles ``HEAD`` requests according to the the `HTTP RFC`_. Likewise,
``OPTIONS`` is automatically implemented for you.
You have no idea what an HTTP method is? Worry not, here is a quick
introduction to HTTP methods and why they matter:
The HTTP method (also often called "the verb") tells the server what the
client wants to *do* with the requested page. The following methods are
very common:
``GET``
The browser tells the server to just *get* the information stored on
that page and send it. This is probably the most common method.
``HEAD``
The browser tells the server to get the information, but it is only
interested in the *headers*, not the content of the page. An
application is supposed to handle that as if a ``GET`` request was
received but to not deliver the actual content. In Flask you don't
have to deal with that at all, the underlying Werkzeug library handles
that for you.
``POST``
The browser tells the server that it wants to *post* some new
information to that URL and that the server must ensure the data is
stored and only stored once. This is how HTML forms usually
transmit data to the server.
``PUT``
Similar to ``POST`` but the server might trigger the store procedure
multiple times by overwriting the old values more than once. Now you
might be asking why this is useful, but there are some good reasons
to do it this way. Consider that the connection is lost during
transmission: in this situation a system between the browser and the
server might receive the request safely a second time without breaking
things. With ``POST`` that would not be possible because it must only
be triggered once.
``DELETE``
Remove the information at the given location.
``OPTIONS``
Provides a quick way for a client to figure out which methods are
supported by this URL. Starting with Flask 0.6, this is implemented
for you automatically.
Now the interesting part is that in HTML4 and XHTML1, the only methods a
form can submit to the server are ``GET`` and ``POST``. But with JavaScript
and future HTML standards you can use the other methods as well. Furthermore
HTTP has become quite popular lately and browsers are no longer the only
clients that are using HTTP. For instance, many revision control systems
use it.
.. _HTTP RFC: http://www.ietf.org/rfc/rfc2068.txt
.. _HTTP RFC: https://www.ietf.org/rfc/rfc2068.txt
Static Files
------------
@ -538,16 +482,16 @@ The Request Object
``````````````````
The request object is documented in the API section and we will not cover
it here in detail (see :class:`~flask.request`). Here is a broad overview of
it here in detail (see :class:`~flask.Request`). Here is a broad overview of
some of the most common operations. First of all you have to import it from
the ``flask`` module::
from flask import request
The current request method is available by using the
:attr:`~flask.request.method` attribute. To access form data (data
:attr:`~flask.Request.method` attribute. To access form data (data
transmitted in a ``POST`` or ``PUT`` request) you can use the
:attr:`~flask.request.form` attribute. Here is a full example of the two
:attr:`~flask.Request.form` attribute. Here is a full example of the two
attributes mentioned above::
@app.route('/login', methods=['POST', 'GET'])
@ -570,7 +514,7 @@ error page is shown instead. So for many situations you don't have to
deal with that problem.
To access parameters submitted in the URL (``?key=value``) you can use the
:attr:`~flask.request.args` attribute::
:attr:`~flask.Request.args` attribute::
searchword = request.args.get('key', '')
@ -579,7 +523,7 @@ We recommend accessing URL parameters with `get` or by catching the
bad request page in that case is not user friendly.
For a full list of methods and attributes of the request object, head over
to the :class:`~flask.request` documentation.
to the :class:`~flask.Request` documentation.
File Uploads

View file

@ -15,7 +15,7 @@ it JavaScript) into the context of a website. To remedy this, developers
have to properly escape text so that it cannot include arbitrary HTML
tags. For more information on that have a look at the Wikipedia article
on `Cross-Site Scripting
<http://en.wikipedia.org/wiki/Cross-site_scripting>`_.
<https://en.wikipedia.org/wiki/Cross-site_scripting>`_.
Flask configures Jinja2 to automatically escape all values unless
explicitly told otherwise. This should rule out all XSS problems caused

View file

@ -167,7 +167,7 @@ Docstring conventions:
"""
Module header:
The module header consists of an utf-8 encoding declaration (if non
The module header consists of a utf-8 encoding declaration (if non
ASCII letters are used, but it is recommended all the time) and a
standard docstring::

View file

@ -33,7 +33,7 @@ In order to test the application, we add a second module
(:file:`flaskr_tests.py`) and create a unittest skeleton there::
import os
import flaskr
from flaskr import flaskr
import unittest
import tempfile
@ -41,7 +41,7 @@ In order to test the application, we add a second module
def setUp(self):
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
flaskr.app.config['TESTING'] = True
flaskr.app.testing = True
self.app = flaskr.app.test_client()
with flaskr.app.app_context():
flaskr.init_db()
@ -98,8 +98,10 @@ test method to our class, like this::
def setUp(self):
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
flaskr.app.testing = True
self.app = flaskr.app.test_client()
flaskr.init_db()
with flaskr.app.app_context():
flaskr.init_db()
def tearDown(self):
os.close(self.db_fd)
@ -208,7 +210,7 @@ temporarily. With this you can access the :class:`~flask.request`,
functions. Here is a full example that demonstrates this approach::
import flask
app = flask.Flask(__name__)
with app.test_request_context('/?name=Peter'):

View file

@ -31,4 +31,4 @@ Here a screenshot of the final application:
Continue with :ref:`tutorial-folders`.
.. _SQLAlchemy: http://www.sqlalchemy.org/
.. _SQLAlchemy: https://www.sqlalchemy.org/

View file

@ -55,7 +55,7 @@ into this file, :file:`flaskr/__init__.py`:
.. sourcecode:: python
from flaskr import app
from .flaskr import app
This import statement brings the application instance into the top-level
of the application package. When it is time to run the application, the

View file

@ -59,7 +59,7 @@ show_entries.html
This template extends the :file:`layout.html` template from above to display the
messages. Note that the ``for`` loop iterates over the messages we passed
in with the :func:`~flask.render_template` function. Notice that the form is
configured to to submit to the `add_entry` view function and use ``POST`` as
configured to submit to the `add_entry` view function and use ``POST`` as
HTTP method:
.. sourcecode:: html+jinja
@ -79,9 +79,9 @@ HTTP method:
{% endif %}
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}</li>
{% else %}
<li><em>Unbelievable. No entries here so far</em>
<li><em>Unbelievable. No entries here so far</em></li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -46,7 +46,7 @@ At this point you can run the tests. Here ``pytest`` will be used.
Run and watch the tests pass, within the top-level :file:`flaskr/`
directory as::
py.test
pytest
Testing + setuptools
--------------------

View file

@ -49,7 +49,7 @@ Any of the following is functionally equivalent::
response = send_file(open(fname), attachment_filename=fname)
response.set_etag(...)
The reason for this is that some file-like objects have a invalid or even
The reason for this is that some file-like objects have an invalid or even
misleading ``name`` attribute. Silently swallowing errors in such cases was not
a satisfying solution.
@ -143,7 +143,7 @@ when there is no request context yet but an application context. The old
``flask.Flask.request_globals_class`` attribute was renamed to
:attr:`flask.Flask.app_ctx_globals_class`.
.. _Flask-OldSessions: http://pythonhosted.org/Flask-OldSessions/
.. _Flask-OldSessions: https://pythonhosted.org/Flask-OldSessions/
Version 0.9
-----------
@ -198,7 +198,7 @@ applications with Flask. Because we want to make upgrading as easy as
possible we tried to counter the problems arising from these changes by
providing a script that can ease the transition.
The script scans your whole application and generates an unified diff with
The script scans your whole application and generates a unified diff with
changes it assumes are safe to apply. However as this is an automated
tool it won't be able to find all use cases and it might miss some. We
internally spread a lot of deprecation warnings all over the place to make