Heavily improved documentation
This commit is contained in:
parent
4e1b3e1134
commit
05f36c7f7e
10 changed files with 486 additions and 44 deletions
5
docs/_templates/sidebarintro.html
vendored
5
docs/_templates/sidebarintro.html
vendored
|
|
@ -5,3 +5,8 @@
|
||||||
not stable yet, but if you have some feedback,
|
not stable yet, but if you have some feedback,
|
||||||
<a href="mailto:armin.ronacher@active-4.com">let me know</a>.
|
<a href="mailto:armin.ronacher@active-4.com">let me know</a>.
|
||||||
</p>
|
</p>
|
||||||
|
<h3>Useful Links</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://pypi.python.org/pypi/Flask">Flask @ PyPI</a></li>
|
||||||
|
<li><a href="http://github.com/mitsuhiko/flask">Flask @ github</a></li>
|
||||||
|
</ul>
|
||||||
|
|
|
||||||
94
docs/_themes/flasky/static/flasky.css_t
vendored
94
docs/_themes/flasky/static/flasky.css_t
vendored
|
|
@ -16,7 +16,7 @@
|
||||||
body {
|
body {
|
||||||
font-family: 'Georgia', serif;
|
font-family: 'Georgia', serif;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
background-color: #111;
|
background-color: #555;
|
||||||
color: #555;
|
color: #555;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
@ -47,15 +47,13 @@ div.body {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.footer {
|
div.footer {
|
||||||
color: #555;
|
color: #ccc;
|
||||||
width: 100%;
|
padding: 10px;
|
||||||
padding: 13px 0;
|
font-size: 0.8em;
|
||||||
text-align: center;
|
|
||||||
font-size: 75%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.footer a {
|
div.footer a {
|
||||||
color: #444;
|
color: white;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +136,7 @@ div.sphinxsidebar input[type=text]{
|
||||||
/* -- body styles ----------------------------------------------------------- */
|
/* -- body styles ----------------------------------------------------------- */
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #003B55;
|
color: #004B6B;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +157,7 @@ div.body h6 {
|
||||||
color: #212224;
|
color: #212224;
|
||||||
margin: 30px 0px 10px 0px;
|
margin: 30px 0px 10px 0px;
|
||||||
padding: 8px 0 5px 10px;
|
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%; }
|
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; }
|
div.body h6 { font-size: 100%; background-color: #eee; }
|
||||||
|
|
||||||
a.headerlink {
|
a.headerlink {
|
||||||
color: #c60f0f;
|
color: white;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.headerlink:hover {
|
a.headerlink:hover {
|
||||||
background-color: #c60f0f;
|
color: #444;
|
||||||
color: white;
|
background: #eaeaea;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.body p, div.body dd, div.body li {
|
div.body p, div.body dd, div.body li {
|
||||||
|
|
@ -218,22 +216,78 @@ p.admonition-title {
|
||||||
p.admonition-title:after {
|
p.admonition-title:after {
|
||||||
content: ":";
|
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 {
|
pre {
|
||||||
|
background: #FDFDFD;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #222;
|
color: #222;
|
||||||
line-height: 1.2em;
|
line-height: 1.3em;
|
||||||
border: 1px solid #C6C9CB;
|
border: 1px solid #f9f9f9;
|
||||||
font-size: 1.1em;
|
margin: 1.5em 3px 1.5em 0;
|
||||||
margin: 1.5em 0 1.5em 0;
|
-webkit-box-shadow: 2px 2px 1px #d8d8d8;
|
||||||
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
|
-moz-box-shadow: 2px 2px 1px #d8d8d8;
|
||||||
-moz-box-shadow: 1px 1px 1px #d8d8d8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tt {
|
tt {
|
||||||
background-color: #ecf0f3;
|
background-color: #ecf0f3;
|
||||||
color: #222;
|
color: #222;
|
||||||
/* padding: 1px 2px; */
|
/* padding: 1px 2px; */
|
||||||
font-size: 1.1em;
|
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
|
||||||
font-family: monospace;
|
-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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,13 @@ Useful Functions and Classes
|
||||||
|
|
||||||
.. autofunction:: url_for
|
.. 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
|
.. autofunction:: redirect
|
||||||
|
|
||||||
|
|
|
||||||
266
docs/deploying.rst
Normal file
266
docs/deploying.rst
Normal file
|
|
@ -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 <module>
|
||||||
|
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
|
||||||
|
|
||||||
|
<VirtualHost *>
|
||||||
|
ServerName example.com
|
||||||
|
|
||||||
|
WSGIDaemonProcess yourapplication user=user1 group=group1 processes=1 threads=5
|
||||||
|
WSGIScriptAlias / /var/www/yourapplication/yourapplication.wsgi
|
||||||
|
|
||||||
|
<Directory /var/www/yourapplication>
|
||||||
|
WSGIProcessGroup yourapplication
|
||||||
|
WSGIApplicationGroup %{GLOBAL}
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
@ -16,10 +16,7 @@ class FlaskyStyle(Style):
|
||||||
Other: "#000000", # class 'x'
|
Other: "#000000", # class 'x'
|
||||||
|
|
||||||
Comment: "italic #8f5902", # class: 'c'
|
Comment: "italic #8f5902", # class: 'c'
|
||||||
Comment.Multiline: "italic #8f5902", # class: 'cm'
|
Comment.Preproc: "noitalic", # class: 'cp'
|
||||||
Comment.Preproc: "italic #8f5902", # class: 'cp'
|
|
||||||
Comment.Single: "italic #8f5902", # class: 'c1'
|
|
||||||
Comment.Special: "italic #8f5902", # class: 'cs'
|
|
||||||
|
|
||||||
Keyword: "bold #004461", # class: 'k'
|
Keyword: "bold #004461", # class: 'k'
|
||||||
Keyword.Constant: "bold #004461", # class: 'kc'
|
Keyword.Constant: "bold #004461", # class: 'kc'
|
||||||
|
|
@ -43,7 +40,7 @@ class FlaskyStyle(Style):
|
||||||
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
||||||
Name.Class: "#000000", # class: 'nc' - to be revised
|
Name.Class: "#000000", # class: 'nc' - to be revised
|
||||||
Name.Constant: "#000000", # class: 'no' - 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.Entity: "#ce5c00", # class: 'ni'
|
||||||
Name.Exception: "bold #cc0000", # class: 'ne'
|
Name.Exception: "bold #cc0000", # class: 'ne'
|
||||||
Name.Function: "#000000", # class: 'nf'
|
Name.Function: "#000000", # class: 'nf'
|
||||||
|
|
@ -57,14 +54,7 @@ class FlaskyStyle(Style):
|
||||||
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
||||||
Name.Variable.Instance: "#000000", # class: 'vi' - 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
|
Number: "#990000", # class: 'm'
|
||||||
# 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'
|
|
||||||
|
|
||||||
Literal: "#000000", # class: 'l'
|
Literal: "#000000", # class: 'l'
|
||||||
Literal.Date: "#000000", # class: 'ld'
|
Literal.Date: "#000000", # class: 'ld'
|
||||||
|
|
@ -88,8 +78,8 @@ class FlaskyStyle(Style):
|
||||||
Generic.Error: "#ef2929", # class: 'gr'
|
Generic.Error: "#ef2929", # class: 'gr'
|
||||||
Generic.Heading: "bold #000080", # class: 'gh'
|
Generic.Heading: "bold #000080", # class: 'gh'
|
||||||
Generic.Inserted: "#00A000", # class: 'gi'
|
Generic.Inserted: "#00A000", # class: 'gi'
|
||||||
Generic.Output: "italic #000000", # class: 'go'
|
Generic.Output: "#888", # class: 'go'
|
||||||
Generic.Prompt: "#8f5902", # class: 'gp'
|
Generic.Prompt: "#745334", # class: 'gp'
|
||||||
Generic.Strong: "bold #000000", # class: 'gs'
|
Generic.Strong: "bold #000000", # class: 'gs'
|
||||||
Generic.Subheading: "bold #800080", # class: 'gu'
|
Generic.Subheading: "bold #800080", # class: 'gu'
|
||||||
Generic.Traceback: "bold #a40000", # class: 'gt'
|
Generic.Traceback: "bold #a40000", # class: 'gt'
|
||||||
|
|
|
||||||
|
|
@ -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`
|
If you are ever in that situation, check out the :ref:`becomingbig`
|
||||||
chapter.
|
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
|
Target Audience
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,5 @@ you want to dive into all the internal parts of Flask, check out the
|
||||||
quickstart
|
quickstart
|
||||||
patterns
|
patterns
|
||||||
api
|
api
|
||||||
|
deploying
|
||||||
becomingbig
|
becomingbig
|
||||||
|
|
|
||||||
|
|
@ -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
|
If you are on OS X or Linux chances are that one of the following two
|
||||||
commands will for for you::
|
commands will for for you::
|
||||||
|
|
||||||
sudo easy_install virtualenv
|
$ sudo easy_install virtualenv
|
||||||
|
|
||||||
or even better::
|
or even better::
|
||||||
|
|
||||||
sudo pip install virtualenv
|
$ sudo pip install virtualenv
|
||||||
|
|
||||||
Changes are you have virtualenv installed on your system then. Maybe it's
|
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
|
even in your package manager (on ubuntu try ``sudo apt-get install
|
||||||
python-virtualenv``).
|
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
|
||||||
<http://pypi.python.org/pypi/virtualenv>`_.
|
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
|
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
|
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
|
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
|
of course as well. Download the `dip` zipfile from the website and unzip
|
||||||
it next to your application.
|
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
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,14 @@ A minimal Flask application looks something like that::
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
If you now start that application with your Python interpreter and head
|
Just save it as `hello.py` or something similar and run it with your
|
||||||
over to `http://localhost:5000/ <http://localhost:5000/>`_, you should see
|
Python interpreter::
|
||||||
your hello world application.
|
|
||||||
|
$ python hello.py
|
||||||
|
* Running on http://localhost:5000/
|
||||||
|
|
||||||
|
Head over to `http://localhost:5000/ <http://localhost:5000/>`_, you should
|
||||||
|
see your hello world greeting.
|
||||||
|
|
||||||
So what did that code do?
|
So what did that code do?
|
||||||
|
|
||||||
|
|
|
||||||
73
flask.py
73
flask.py
|
|
@ -79,6 +79,8 @@ def flash(message):
|
||||||
"""Flashes a message to the next request. In order to remove the
|
"""Flashes a message to the next request. In order to remove the
|
||||||
flashed message from the session and to display it to the user,
|
flashed message from the session and to display it to the user,
|
||||||
the template has to call :func:`get_flashed_messages`.
|
the template has to call :func:`get_flashed_messages`.
|
||||||
|
|
||||||
|
:param message: the message to be flashed.
|
||||||
"""
|
"""
|
||||||
session['_flashes'] = (session.get('_flashes', [])) + [message]
|
session['_flashes'] = (session.get('_flashes', [])) + [message]
|
||||||
|
|
||||||
|
|
@ -98,6 +100,10 @@ def get_flashed_messages():
|
||||||
def render_template(template_name, **context):
|
def render_template(template_name, **context):
|
||||||
"""Renders a template from the template folder with the given
|
"""Renders a template from the template folder with the given
|
||||||
context.
|
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)
|
current_app.update_template_context(context)
|
||||||
return current_app.jinja_env.get_template(template_name).render(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):
|
def render_template_string(source, **context):
|
||||||
"""Renders a template from the given template source string
|
"""Renders a template from the given template source string
|
||||||
with the given context.
|
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)
|
current_app.update_template_context(context)
|
||||||
return current_app.jinja_env.from_string(source).render(context)
|
return current_app.jinja_env.from_string(source).render(context)
|
||||||
|
|
@ -222,6 +233,9 @@ class Flask(object):
|
||||||
def update_template_context(self, context):
|
def update_template_context(self, context):
|
||||||
"""Update the template context with some commonly used variables.
|
"""Update the template context with some commonly used variables.
|
||||||
This injects request, session and g into the template context.
|
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
|
reqctx = _request_ctx_stack.top
|
||||||
context['request'] = reqctx.request
|
context['request'] = reqctx.request
|
||||||
|
|
@ -232,6 +246,13 @@ class Flask(object):
|
||||||
"""Runs the application on a local development server. If the
|
"""Runs the application on a local development server. If the
|
||||||
:attr:`debug` flag is set the server will automatically reload
|
:attr:`debug` flag is set the server will automatically reload
|
||||||
for code changes and show a debugger in case an exception happened.
|
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
|
from werkzeug import run_simple
|
||||||
if 'debug' in options:
|
if 'debug' in options:
|
||||||
|
|
@ -268,6 +289,9 @@ class Flask(object):
|
||||||
with app.open_resource('schema.sql') as f:
|
with app.open_resource('schema.sql') as f:
|
||||||
contents = f.read()
|
contents = f.read()
|
||||||
do_something_with(contents)
|
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)
|
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
|
"""Creates or opens a new session. Default implementation stores all
|
||||||
session data in a signed cookie. This requires that the
|
session data in a signed cookie. This requires that the
|
||||||
:attr:`secret_key` is set.
|
:attr:`secret_key` is set.
|
||||||
|
|
||||||
|
:param request: an instance of :attr:`request_class`.
|
||||||
"""
|
"""
|
||||||
key = self.secret_key
|
key = self.secret_key
|
||||||
if key is not None:
|
if key is not None:
|
||||||
|
|
@ -284,6 +310,11 @@ class Flask(object):
|
||||||
def save_session(self, session, response):
|
def save_session(self, session, response):
|
||||||
"""Saves the session if it needs updates. For the default
|
"""Saves the session if it needs updates. For the default
|
||||||
implementation, check :meth:`open_session`.
|
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:
|
if session is not None:
|
||||||
session.save_cookie(response, self.session_cookie_name)
|
session.save_cookie(response, self.session_cookie_name)
|
||||||
|
|
@ -304,6 +335,13 @@ class Flask(object):
|
||||||
pass
|
pass
|
||||||
app.add_url_rule('index', '/')
|
app.add_url_rule('index', '/')
|
||||||
app.view_functions['index'] = 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['endpoint'] = endpoint
|
||||||
options.setdefault('methods', ('GET',))
|
options.setdefault('methods', ('GET',))
|
||||||
|
|
@ -363,6 +401,7 @@ class Flask(object):
|
||||||
The :meth:`route` decorator accepts a couple of other arguments
|
The :meth:`route` decorator accepts a couple of other arguments
|
||||||
as well:
|
as well:
|
||||||
|
|
||||||
|
:param rule: the URL rule as string
|
||||||
:param methods: a list of methods this rule should be limited
|
:param methods: a list of methods this rule should be limited
|
||||||
to (``GET``, ``POST`` etc.). By default a rule
|
to (``GET``, ``POST`` etc.). By default a rule
|
||||||
just listens for ``GET`` (and implicitly ``HEAD``).
|
just listens for ``GET`` (and implicitly ``HEAD``).
|
||||||
|
|
@ -370,6 +409,8 @@ class Flask(object):
|
||||||
subdomain matching is in use.
|
subdomain matching is in use.
|
||||||
:param strict_slashes: can be used to disable the strict slashes
|
:param strict_slashes: can be used to disable the strict slashes
|
||||||
setting for this rule. See above.
|
setting for this rule. See above.
|
||||||
|
:param options: other options to be forwarded to the underlying
|
||||||
|
:class:`~werkzeug.routing.Rule` object.
|
||||||
"""
|
"""
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
self.add_url_rule(rule, f.__name__, **options)
|
self.add_url_rule(rule, f.__name__, **options)
|
||||||
|
|
@ -392,6 +433,8 @@ class Flask(object):
|
||||||
def page_not_found():
|
def page_not_found():
|
||||||
return 'This page does not exist', 404
|
return 'This page does not exist', 404
|
||||||
app.error_handlers[404] = page_not_found
|
app.error_handlers[404] = page_not_found
|
||||||
|
|
||||||
|
:param code: the code as integer for the handler
|
||||||
"""
|
"""
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
self.error_handlers[code] = f
|
self.error_handlers[code] = f
|
||||||
|
|
@ -440,6 +483,22 @@ class Flask(object):
|
||||||
def make_response(self, rv):
|
def make_response(self, rv):
|
||||||
"""Converts the return value from a view function to a real
|
"""Converts the return value from a view function to a real
|
||||||
response object that is an instance of :attr:`response_class`.
|
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):
|
if isinstance(rv, self.response_class):
|
||||||
return rv
|
return rv
|
||||||
|
|
@ -464,6 +523,10 @@ class Flask(object):
|
||||||
def process_response(self, response):
|
def process_response(self, response):
|
||||||
"""Can be overridden in order to modify the response object
|
"""Can be overridden in order to modify the response object
|
||||||
before it's sent to the WSGI server.
|
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
|
session = _request_ctx_stack.top.session
|
||||||
if session is not None:
|
if session is not None:
|
||||||
|
|
@ -477,6 +540,11 @@ class Flask(object):
|
||||||
`__call__` so that middlewares can be applied:
|
`__call__` so that middlewares can be applied:
|
||||||
|
|
||||||
app.wsgi_app = MyMiddleware(app.wsgi_app)
|
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):
|
with self.request_context(environ):
|
||||||
rv = self.preprocess_request()
|
rv = self.preprocess_request()
|
||||||
|
|
@ -497,6 +565,8 @@ class Flask(object):
|
||||||
|
|
||||||
with app.request_context(environ):
|
with app.request_context(environ):
|
||||||
do_something_with(request)
|
do_something_with(request)
|
||||||
|
|
||||||
|
:params environ: a WSGI environment
|
||||||
"""
|
"""
|
||||||
_request_ctx_stack.push(_RequestContext(self, environ))
|
_request_ctx_stack.push(_RequestContext(self, environ))
|
||||||
try:
|
try:
|
||||||
|
|
@ -506,7 +576,8 @@ class Flask(object):
|
||||||
|
|
||||||
def test_request_context(self, *args, **kwargs):
|
def test_request_context(self, *args, **kwargs):
|
||||||
"""Creates a WSGI environment from the given values (see
|
"""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))
|
return self.request_context(create_environ(*args, **kwargs))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue