From 05f36c7f7e2df36ee28f90d99632162579b1287c Mon Sep 17 00:00:00 2001
From: Armin Ronacher
Date: Sun, 11 Apr 2010 02:20:10 +0200
Subject: [PATCH] Heavily improved documentation
---
docs/_templates/sidebarintro.html | 5 +
docs/_themes/flasky/static/flasky.css_t | 94 +++++++--
docs/api.rst | 8 +-
docs/deploying.rst | 266 ++++++++++++++++++++++++
docs/flaskext.py | 20 +-
docs/foreword.rst | 9 +
docs/index.rst | 1 +
docs/installation.rst | 43 +++-
docs/quickstart.rst | 11 +-
flask.py | 73 ++++++-
10 files changed, 486 insertions(+), 44 deletions(-)
create mode 100644 docs/deploying.rst
diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html
index 46e01d5c..06bd737e 100644
--- a/docs/_templates/sidebarintro.html
+++ b/docs/_templates/sidebarintro.html
@@ -5,3 +5,8 @@
not stable yet, but if you have some feedback,
let me know.
+Useful Links
+
diff --git a/docs/_themes/flasky/static/flasky.css_t b/docs/_themes/flasky/static/flasky.css_t
index 05caf2f7..bd829c0c 100644
--- a/docs/_themes/flasky/static/flasky.css_t
+++ b/docs/_themes/flasky/static/flasky.css_t
@@ -16,7 +16,7 @@
body {
font-family: 'Georgia', serif;
font-size: 100%;
- background-color: #111;
+ background-color: #555;
color: #555;
margin: 0;
padding: 0;
@@ -47,15 +47,13 @@ div.body {
}
div.footer {
- color: #555;
- width: 100%;
- padding: 13px 0;
- text-align: center;
- font-size: 75%;
+ color: #ccc;
+ padding: 10px;
+ font-size: 0.8em;
}
div.footer a {
- color: #444;
+ color: white;
text-decoration: underline;
}
@@ -138,7 +136,7 @@ div.sphinxsidebar input[type=text]{
/* -- body styles ----------------------------------------------------------- */
a {
- color: #003B55;
+ color: #004B6B;
text-decoration: none;
}
@@ -159,7 +157,7 @@ div.body h6 {
color: #212224;
margin: 30px 0px 10px 0px;
padding: 8px 0 5px 10px;
- text-shadow: 0px 1px 0 white
+ text-shadow: 0px 1px 0 white;
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
@@ -170,14 +168,14 @@ div.body h5 { font-size: 100%; background-color: #eee; }
div.body h6 { font-size: 100%; background-color: #eee; }
a.headerlink {
- color: #c60f0f;
+ color: white;
padding: 0 4px;
text-decoration: none;
}
a.headerlink:hover {
- background-color: #c60f0f;
- color: white;
+ color: #444;
+ background: #eaeaea;
}
div.body p, div.body dd, div.body li {
@@ -218,22 +216,78 @@ p.admonition-title {
p.admonition-title:after {
content: ":";
}
+
+pre, tt {
+ font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.9em;
+}
+
+tt.descname, tt.descclassname {
+ font-size: 0.95em;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+}
+
+tt.descname {
+ padding-right: 0.08em;
+}
+
+table.docutils {
+ border: 1px solid #888;
+ -webkit-box-shadow: 2px 2px 1px #d8d8d8;
+ -moz-box-shadow: 2px 2px 1px #d8d8d8;
+}
+
+table.docutils td, table.docutils th {
+ border: 1px solid #888;
+ padding: 0.25em 0.7em;
+}
+
+table.field-list {
+ border: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+}
+
+table.field-list th {
+ padding: 0 0.8em 0 0;
+}
+
+table.field-list td {
+ padding: 0;
+}
pre {
+ background: #FDFDFD;
padding: 10px;
color: #222;
- line-height: 1.2em;
- border: 1px solid #C6C9CB;
- font-size: 1.1em;
- margin: 1.5em 0 1.5em 0;
- -webkit-box-shadow: 1px 1px 1px #d8d8d8;
- -moz-box-shadow: 1px 1px 1px #d8d8d8;
+ line-height: 1.3em;
+ border: 1px solid #f9f9f9;
+ margin: 1.5em 3px 1.5em 0;
+ -webkit-box-shadow: 2px 2px 1px #d8d8d8;
+ -moz-box-shadow: 2px 2px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
- font-size: 1.1em;
- font-family: monospace;
+ -webkit-box-shadow: 1px 1px 1px #d8d8d8;
+ -moz-box-shadow: 1px 1px 1px #d8d8d8;
+}
+
+tt.xref, a tt {
+ background-color: #FBFBFB;
+}
+
+a:hover tt {
+ background: #EEE;
+}
+
+div.document + div.related {
+ background: #aaa;
+}
+
+div.document + div.related a {
+ color: white;
}
diff --git a/docs/api.rst b/docs/api.rst
index eefdf71c..98614ead 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -163,7 +163,13 @@ Useful Functions and Classes
.. autofunction:: url_for
-.. autofunction:: abort
+.. function:: abort(code)
+
+ Raises an :exc:`~werkzeug.exception.HTTPException` for the given
+ status code. For example to abort request handling with a page not
+ found exception, you would call ``abort(404)``.
+
+ :param code: the HTTP error code.
.. autofunction:: redirect
diff --git a/docs/deploying.rst b/docs/deploying.rst
new file mode 100644
index 00000000..345d7ee9
--- /dev/null
+++ b/docs/deploying.rst
@@ -0,0 +1,266 @@
+Deployment Options
+==================
+
+Depending on what you have available there are multiple ways to run Flask
+applications. A very common method is to use the builtin server during
+development and maybe behind a proxy for simple applications, but there
+are more options available.
+
+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 application object
+is the actual WSGI application.
+
+
+FastCGI
+-------
+
+A very popular deployment setup on servers like `lighttpd`_ and `nginx`_
+is FastCGI. 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.
+
+Creating a `.fcgi` file
+```````````````````````
+
+First you need to create the FastCGI server file. Let's call it
+`yourapplication.fcgi`::
+
+ #!/usr/bin/python
+ from flup.server.fcgi import WSGIServer
+ from yourapplication import app
+
+ WSGIServer(app).run()
+
+This is enough for Apache to work, however lighttpd and nginx need a
+socket to communicate with the FastCGI server. For that to work you
+need to pass the path to the socket to the
+:class:`~flup.server.fcgi.WSGIServer`::
+
+ WSGIServer(application, bindAddress='/path/to/fcgi.sock').run()
+
+The path has to be the exact same path you define in the server
+config.
+
+Save the `yourapplication.fcgi` file somewhere you will find it again.
+It makes sense to have that in `/var/www/yourapplication` or something
+similar.
+
+Make sure to set the executable bit on that file so that the servers
+can execute it::
+
+ # chmod +x /var/www/yourapplication/yourapplication.fcgi
+
+Configuring lighttpd
+````````````````````
+
+A basic FastCGI configuration for lighttpd looks like that::
+
+ fastcgi.server = ("/yourapplication" =>
+ "yourapplication" => (
+ "socket" => "/tmp/yourapplication-fcgi.sock",
+ "bin-path" => "/var/www/yourapplication/yourapplication.fcgi",
+ "check-local" => "disable"
+ )
+ )
+
+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 `~werkzeug.contrib.fixers.LighttpdCGIRootFix` middleware.
+
+Make sure to apply it only if you are mounting the application the URL
+root.
+
+Configuring nginx
+`````````````````
+
+Installing FastCGI applications on nginx is a bit tricky because by default
+some FastCGI parameters are not properly forwarded.
+
+A basic FastCGI configuration for nginx looks like this::
+
+ location /yourapplication/ {
+ include fastcgi_params;
+ if ($uri ~ ^/yourapplication/(.*)?) {
+ set $path_url $1;
+ }
+ fastcgi_param PATH_INFO $path_url;
+ fastcgi_param SCRIPT_NAME /yourapplication;
+ fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
+ }
+
+This configuration binds the application to `/yourapplication`. If you want
+to have it in the URL root it's a bit easier because you don't have to figure
+out how to calculate `PATH_INFO` and `SCRIPT_NAME`::
+
+ location /yourapplication/ {
+ include fastcgi_params;
+ fastcgi_param PATH_INFO $fastcgi_script_name;
+ fastcgi_param SCRIPT_NAME "";
+ fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
+ }
+
+Since Nginx doesn't load FastCGI apps, you have to do it by yourself. You
+can either write an `init.d` script for that or execute it inside a screen
+session::
+
+ $ screen
+ $ /var/www/yourapplication/yourapplication.fcgi
+
+Debugging
+`````````
+
+FastCGI deployments tend to be hard to debug on most webservers. Very often the
+only thing the server log tells you is something along the lines of "premature
+end of headers". In order to debug the application the only thing that can
+really give you ideas why it breaks is switching to the correct user and
+executing the application by hand.
+
+This example assumes your application is called `application.fcgi` and that your
+webserver user is `www-data`::
+
+ $ su www-data
+ $ cd /var/www/yourapplication
+ $ python application.fcgi
+ Traceback (most recent call last):
+ File "yourapplication.fcg", line 4, in
+ ImportError: No module named yourapplication
+
+In this case the error seems to be "yourapplication" not being on the python
+path. Common problems are:
+
+- relative paths being used. Don't rely on the current working directory
+- the code depending on environment variables that are not set by the
+ web server.
+- different python interpreters being used.
+
+.. _lighttpd: http://www.lighttpd.net/
+.. _nginx: http://nginx.net/
+.. _flup: http://trac.saddi.com/flup
+
+
+mod_wsgi (Apache)
+-----------------
+
+If you are using the `Apache`_ webserver you should consider using `mod_wsgi`_.
+
+.. _Apache: http://httpd.apache.org/
+
+Installing `mod_wsgi`
+`````````````````````
+
+If you don't have `mod_wsgi` installed yet you have to either install it using
+a package manager or compile it yourself.
+
+The mod_wsgi `installation instructions`_ cover installation instructions for
+source installations on UNIX systems.
+
+If you are using ubuntu / debian you can apt-get it and activate it as follows::
+
+ # apt-get install libapache2-mod-wsgi
+
+On FreeBSD install `mod_wsgi` by compiling the `www/mod_wsgi` port or by using
+pkg_add::
+
+ # pkg_add -r mod_wsgi
+
+If you are using pkgsrc you can install `mod_wsgi` by compiling the
+`www/ap2-wsgi` package.
+
+If you encounter segfaulting child processes after the first apache reload you
+can safely ignore them. Just restart the server.
+
+Creating a `.wsgi` file
+```````````````````````
+
+To run your application you need a `yourapplication.wsgi` file. This file
+contains the code `mod_wsgi` is executing on startup to get the application
+object. The object called `application` in that file is then used as
+application.
+
+For most applications the following file should be sufficient::
+
+ from yourapplication import app as application
+
+If you don't have a factory function for application creation but a singleton
+instance you can directly import that one as `application`.
+
+Store that file somewhere where you will find it again (eg:
+`/var/www/yourapplication`) and make sure that `yourapplication` and all
+the libraries that are in use are on the python load path. If you don't
+want to install it system wide consider using a `virtual python`_ instance.
+
+Configuring Apache
+``````````````````
+
+The last thing you have to do is to create an Apache configuration file for
+your application. In this example we are telling `mod_wsgi` to execute the
+application under a different user for security reasons:
+
+.. sourcecode:: apache
+
+
+ ServerName example.com
+
+ WSGIDaemonProcess yourapplication user=user1 group=group1 processes=1 threads=5
+ WSGIScriptAlias / /var/www/yourapplication/yourapplication.wsgi
+
+
+ WSGIProcessGroup yourapplication
+ WSGIApplicationGroup %{GLOBAL}
+ Order deny,allow
+ Allow from all
+
+
+
+For more information consult the `mod_wsgi wiki`_.
+
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+.. _installation instructions: http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide
+.. _virtual python: http://pypi.python.org/pypi/virtualenv
+.. _mod_wsgi wiki: http://code.google.com/p/modwsgi/wiki/
+
+
+CGI
+---
+
+If all other deployment methods do not work, CGI will work for sure. CGI
+is supported by all major browsers but usually has a less-than-optimal
+performance.
+
+This is also the way you can use a Flask application on Google's
+`AppEngine`_, there however the execution does happen in a CGI-like
+environment. The application's performance is unaffected because of that.
+
+.. _AppEngine: http://code.google.com/appengine/
+
+Creating a `.cgi` file
+``````````````````````
+
+First you need to create the CGI application file. Let's call it
+`yourapplication.cgi`::
+
+ #!/usr/bin/python
+ from wsgiref.handlers import CGIHandler
+ from yourapplication import app
+
+ CGIHandler().run(app)
+
+If you're running Python 2.4 you will need the :mod:`wsgiref` package. Python
+2.5 and higher ship this as part of the standard library.
+
+Server Setup
+````````````
+
+Usually there are two ways to configure the server. Either just copy the
+`.cgi` into a `cgi-bin` (and use `mod_rerwite` 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:
+
+.. sourcecode:: apache
+
+ ScriptName /app /path/to/the/application.cgi
+
+For more information consult the documentation of your webserver.
diff --git a/docs/flaskext.py b/docs/flaskext.py
index 85331eff..33f47449 100644
--- a/docs/flaskext.py
+++ b/docs/flaskext.py
@@ -16,10 +16,7 @@ class FlaskyStyle(Style):
Other: "#000000", # class 'x'
Comment: "italic #8f5902", # class: 'c'
- Comment.Multiline: "italic #8f5902", # class: 'cm'
- Comment.Preproc: "italic #8f5902", # class: 'cp'
- Comment.Single: "italic #8f5902", # class: 'c1'
- Comment.Special: "italic #8f5902", # class: 'cs'
+ Comment.Preproc: "noitalic", # class: 'cp'
Keyword: "bold #004461", # class: 'k'
Keyword.Constant: "bold #004461", # class: 'kc'
@@ -43,7 +40,7 @@ class FlaskyStyle(Style):
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
Name.Class: "#000000", # class: 'nc' - to be revised
Name.Constant: "#000000", # class: 'no' - to be revised
- Name.Decorator: "#999", # class: 'nd' - to be revised
+ Name.Decorator: "#888", # class: 'nd' - to be revised
Name.Entity: "#ce5c00", # class: 'ni'
Name.Exception: "bold #cc0000", # class: 'ne'
Name.Function: "#000000", # class: 'nf'
@@ -57,14 +54,7 @@ class FlaskyStyle(Style):
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
- # since the tango light blue does not show up well in text, we choose
- # a pure blue instead.
- Number: "bold #0000cf", # class: 'm'
- Number.Float: "bold #0000cf", # class: 'mf'
- Number.Hex: "bold #0000cf", # class: 'mh'
- Number.Integer: "bold #0000cf", # class: 'mi'
- Number.Integer.Long: "bold #0000cf", # class: 'il'
- Number.Oct: "bold #0000cf", # class: 'mo'
+ Number: "#990000", # class: 'm'
Literal: "#000000", # class: 'l'
Literal.Date: "#000000", # class: 'ld'
@@ -88,8 +78,8 @@ class FlaskyStyle(Style):
Generic.Error: "#ef2929", # class: 'gr'
Generic.Heading: "bold #000080", # class: 'gh'
Generic.Inserted: "#00A000", # class: 'gi'
- Generic.Output: "italic #000000", # class: 'go'
- Generic.Prompt: "#8f5902", # class: 'gp'
+ Generic.Output: "#888", # class: 'go'
+ Generic.Prompt: "#745334", # class: 'gp'
Generic.Strong: "bold #000000", # class: 'gs'
Generic.Subheading: "bold #800080", # class: 'gu'
Generic.Traceback: "bold #a40000", # class: 'gt'
diff --git a/docs/foreword.rst b/docs/foreword.rst
index 79243d3b..580cf37d 100644
--- a/docs/foreword.rst
+++ b/docs/foreword.rst
@@ -36,6 +36,15 @@ something the framework just cannot do for you without modification.
If you are ever in that situation, check out the :ref:`becomingbig`
chapter.
+A Framework and An Example
+--------------------------
+
+Flask is not only a microframework, it is also an example. Based on
+Flask, there will be a series of blog posts that explain how to create a
+framework. Flask itself is just one way to implement a framework on top
+of existing libraries. Unlike many other microframeworks Flask does not
+try to implement anything on its own, it reuses existing code.
+
Target Audience
---------------
diff --git a/docs/index.rst b/docs/index.rst
index 290656ea..81528203 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -20,4 +20,5 @@ you want to dive into all the internal parts of Flask, check out the
quickstart
patterns
api
+ deploying
becomingbig
diff --git a/docs/installation.rst b/docs/installation.rst
index b8375cd7..89e5a680 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -41,18 +41,19 @@ So let's see how that works!
If you are on OS X or Linux chances are that one of the following two
commands will for for you::
- sudo easy_install virtualenv
+ $ sudo easy_install virtualenv
or even better::
- sudo pip install virtualenv
+ $ sudo pip install virtualenv
Changes are you have virtualenv installed on your system then. Maybe it's
even in your package manager (on ubuntu try ``sudo apt-get install
python-virtualenv``).
-On windows, just installed virtualenv from the `Python Package Index
-`_.
+If you are on Windows and missing the `easy_install` command you have to
+install it first. Check the :ref:`windows-easy-install` section for more
+information about how to do that.
So now that you have virtualenv running just fire up a shell and create
your own environment. I usually create a folder and a `env` folder
@@ -101,3 +102,37 @@ The Drop into Place Version
Now I really don't recommend this way on using Flask, but you can do that
of course as well. Download the `dip` zipfile from the website and unzip
it next to your application.
+
+.. _windows-easy-install:
+
+`easy_install` on Windows
+-------------------------
+
+On Windows installation of `easy_install` is a little bit tricker because
+on Windows slightly different rules apply, but it's not a biggy. The
+easiest way to accomplish that is downloading the `ez_setup.py`_ file and
+running it. (Double clicking should do the trick)
+
+Once you have done that it's important to add the `easy_install` command
+and other Python scripts to the path. To do that you have to add the
+Python installation's Script folder to the `PATH` variable.
+
+To do that, click right on your "Computer" desktop icon and click
+"Properties". On Windows Vista and Windows 7 then click on "Advanced System
+settings", on Windows XP click on the "Advanced" tab instead. Then click
+on the "Environment variables" button and double click on the "Path"
+variable in the "System variables" section.
+
+There append the path of your Python interpreter's Script folder to the
+end of the last (make sure you delimit it from existing values with a
+semicolon). Assuming you are using Python 2.6 on the default path, add
+the following value::
+
+ ;C:\Python26\Scripts
+
+Then you are done. To check if it worked, open the cmd and execute
+"easy_install". If you have UAC enabled it should prompt you for admin
+privileges.
+
+
+.. _ez_setup.py: http://peak.telecommunity.com/dist/ez_setup.py
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index 45a3f0f6..429d7ab3 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -23,9 +23,14 @@ A minimal Flask application looks something like that::
if __name__ == '__main__':
app.run()
-If you now start that application with your Python interpreter and head
-over to `http://localhost:5000/ `_, you should see
-your hello world application.
+Just save it as `hello.py` or something similar and run it with your
+Python interpreter::
+
+ $ python hello.py
+ * Running on http://localhost:5000/
+
+Head over to `http://localhost:5000/ `_, you should
+see your hello world greeting.
So what did that code do?
diff --git a/flask.py b/flask.py
index 344cae3b..1ea239f8 100644
--- a/flask.py
+++ b/flask.py
@@ -79,6 +79,8 @@ def flash(message):
"""Flashes a message to the next request. In order to remove the
flashed message from the session and to display it to the user,
the template has to call :func:`get_flashed_messages`.
+
+ :param message: the message to be flashed.
"""
session['_flashes'] = (session.get('_flashes', [])) + [message]
@@ -98,6 +100,10 @@ def get_flashed_messages():
def render_template(template_name, **context):
"""Renders a template from the template folder with the given
context.
+
+ :param template_name: the name of the template to be rendered
+ :param context: the variables that should be available in the
+ context of the template.
"""
current_app.update_template_context(context)
return current_app.jinja_env.get_template(template_name).render(context)
@@ -106,6 +112,11 @@ def render_template(template_name, **context):
def render_template_string(source, **context):
"""Renders a template from the given template source string
with the given context.
+
+ :param template_name: the sourcecode of the template to be
+ rendered
+ :param context: the variables that should be available in the
+ context of the template.
"""
current_app.update_template_context(context)
return current_app.jinja_env.from_string(source).render(context)
@@ -222,6 +233,9 @@ class Flask(object):
def update_template_context(self, context):
"""Update the template context with some commonly used variables.
This injects request, session and g into the template context.
+
+ :param context: the context as a dictionary that is updated in place
+ to add extra variables.
"""
reqctx = _request_ctx_stack.top
context['request'] = reqctx.request
@@ -232,6 +246,13 @@ class Flask(object):
"""Runs the application on a local development server. If the
:attr:`debug` flag is set the server will automatically reload
for code changes and show a debugger in case an exception happened.
+
+ :param host: the hostname to listen on. set this to ``'0.0.0.0'``
+ to have the server available externally as well.
+ :param port: the port of the webserver
+ :param options: the options to be forwarded to the underlying
+ Werkzeug server. See :func:`werkzeug.run_simple`
+ for more information.
"""
from werkzeug import run_simple
if 'debug' in options:
@@ -268,6 +289,9 @@ class Flask(object):
with app.open_resource('schema.sql') as f:
contents = f.read()
do_something_with(contents)
+
+ :param resource: the name of the resource. To access resources within
+ subfolders use forward slashes as separator.
"""
return pkg_resources.resource_stream(self.package_name, resource)
@@ -275,6 +299,8 @@ class Flask(object):
"""Creates or opens a new session. Default implementation stores all
session data in a signed cookie. This requires that the
:attr:`secret_key` is set.
+
+ :param request: an instance of :attr:`request_class`.
"""
key = self.secret_key
if key is not None:
@@ -284,6 +310,11 @@ class Flask(object):
def save_session(self, session, response):
"""Saves the session if it needs updates. For the default
implementation, check :meth:`open_session`.
+
+ :param session: the session to be saved (a
+ :class:`~werkzeug.contrib.securecookie.SecureCookie`
+ object)
+ :param request: an instance of :attr:`response_class`
"""
if session is not None:
session.save_cookie(response, self.session_cookie_name)
@@ -304,6 +335,13 @@ class Flask(object):
pass
app.add_url_rule('index', '/')
app.view_functions['index'] = index
+
+ :param rule: the URL rule as string
+ :param endpoint: the endpoint for the registered URL rule. Flask
+ itself assumes the name of the view function as
+ endpoint
+ :param options: the options to be forwarded to the underlying
+ :class:`~werkzeug.routing.Rule` object
"""
options['endpoint'] = endpoint
options.setdefault('methods', ('GET',))
@@ -363,6 +401,7 @@ class Flask(object):
The :meth:`route` decorator accepts a couple of other arguments
as well:
+ :param rule: the URL rule as string
:param methods: a list of methods this rule should be limited
to (``GET``, ``POST`` etc.). By default a rule
just listens for ``GET`` (and implicitly ``HEAD``).
@@ -370,6 +409,8 @@ class Flask(object):
subdomain matching is in use.
:param strict_slashes: can be used to disable the strict slashes
setting for this rule. See above.
+ :param options: other options to be forwarded to the underlying
+ :class:`~werkzeug.routing.Rule` object.
"""
def decorator(f):
self.add_url_rule(rule, f.__name__, **options)
@@ -392,6 +433,8 @@ class Flask(object):
def page_not_found():
return 'This page does not exist', 404
app.error_handlers[404] = page_not_found
+
+ :param code: the code as integer for the handler
"""
def decorator(f):
self.error_handlers[code] = f
@@ -440,6 +483,22 @@ class Flask(object):
def make_response(self, rv):
"""Converts the return value from a view function to a real
response object that is an instance of :attr:`response_class`.
+
+ The following types are allowd for `rv`:
+
+ ======================= ===========================================
+ :attr:`response_class` the object is returned unchanged
+ :class:`str` a response object is created with the
+ string as body
+ :class:`unicode` a response object is created with the
+ string encoded to utf-8 as body
+ :class:`tuple` the response object is created with the
+ contents of the tuple as arguments
+ a WSGI function the function is called as WSGI application
+ and buffered as response object
+ ======================= ===========================================
+
+ :param rv: the return value from the view function
"""
if isinstance(rv, self.response_class):
return rv
@@ -464,6 +523,10 @@ class Flask(object):
def process_response(self, response):
"""Can be overridden in order to modify the response object
before it's sent to the WSGI server.
+
+ :param response: a :attr:`response_class` object.
+ :return: a new response object or the same, has to be an
+ instance of :attr:`response_class`.
"""
session = _request_ctx_stack.top.session
if session is not None:
@@ -477,6 +540,11 @@ class Flask(object):
`__call__` so that middlewares can be applied:
app.wsgi_app = MyMiddleware(app.wsgi_app)
+
+ :param environ: a WSGI environment
+ :param start_response: a callable accepting a status code,
+ a list of headers and an optional
+ exception context to start the response
"""
with self.request_context(environ):
rv = self.preprocess_request()
@@ -497,6 +565,8 @@ class Flask(object):
with app.request_context(environ):
do_something_with(request)
+
+ :params environ: a WSGI environment
"""
_request_ctx_stack.push(_RequestContext(self, environ))
try:
@@ -506,7 +576,8 @@ class Flask(object):
def test_request_context(self, *args, **kwargs):
"""Creates a WSGI environment from the given values (see
- :func:`werkzeug.create_environ` for more information).
+ :func:`werkzeug.create_environ` for more information, this
+ function accepts the same arguments).
"""
return self.request_context(create_environ(*args, **kwargs))