mirror of https://github.com/mitsuhiko/flask.git
Armin Ronacher
15 years ago
13 changed files with 808 additions and 10 deletions
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,7 @@ |
|||||||
|
<h3>About Flask</h3> |
||||||
|
<p> |
||||||
|
Flask is a micro webdevelopment framework for Python. You are currently |
||||||
|
looking at the documentation of the development version. Things are |
||||||
|
not stable yet, but if you have some feedback, |
||||||
|
<a href="mailto:armin.ronacher@active-4.com">let me know</a>. |
||||||
|
</p> |
@ -0,0 +1,3 @@ |
|||||||
|
<p class="logo"><a href="{{ pathto(master_doc) }}"> |
||||||
|
<img class="logo" src="{{ pathto('_static/flask.png', 1) }}" alt="Logo"/> |
||||||
|
</a></p> |
@ -0,0 +1,239 @@ |
|||||||
|
/* |
||||||
|
* flasky.css_t |
||||||
|
* ~~~~~~~~~~~~ |
||||||
|
* |
||||||
|
* Sphinx stylesheet -- flasky theme based on nature theme. |
||||||
|
* |
||||||
|
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. |
||||||
|
* :license: BSD, see LICENSE for details. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
@import url("basic.css"); |
||||||
|
|
||||||
|
/* -- page layout ----------------------------------------------------------- */ |
||||||
|
|
||||||
|
body { |
||||||
|
font-family: 'Georgia', serif; |
||||||
|
font-size: 100%; |
||||||
|
background-color: #111; |
||||||
|
color: #555; |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
|
||||||
|
div.documentwrapper { |
||||||
|
float: left; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
div.bodywrapper { |
||||||
|
margin: 0 0 0 230px; |
||||||
|
} |
||||||
|
|
||||||
|
hr { |
||||||
|
border: 1px solid #B1B4B6; |
||||||
|
} |
||||||
|
|
||||||
|
div.document { |
||||||
|
background-color: #eee; |
||||||
|
} |
||||||
|
|
||||||
|
div.body { |
||||||
|
background-color: #ffffff; |
||||||
|
color: #3E4349; |
||||||
|
padding: 0 30px 30px 30px; |
||||||
|
font-size: 0.9em; |
||||||
|
} |
||||||
|
|
||||||
|
div.footer { |
||||||
|
color: #555; |
||||||
|
width: 100%; |
||||||
|
padding: 13px 0; |
||||||
|
text-align: center; |
||||||
|
font-size: 75%; |
||||||
|
} |
||||||
|
|
||||||
|
div.footer a { |
||||||
|
color: #444; |
||||||
|
text-decoration: underline; |
||||||
|
} |
||||||
|
|
||||||
|
div.related { |
||||||
|
background-color: #774117; |
||||||
|
line-height: 32px; |
||||||
|
color: #fff; |
||||||
|
text-shadow: 0px 1px 0 #444; |
||||||
|
font-size: 0.9em; |
||||||
|
} |
||||||
|
|
||||||
|
div.related a { |
||||||
|
color: #E9D1C1; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar { |
||||||
|
font-size: 0.75em; |
||||||
|
line-height: 1.5em; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebarwrapper { |
||||||
|
padding: 20px 0 20px 0; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebarwrapper p.logo { |
||||||
|
padding: 0 0 10px 0; |
||||||
|
margin: 0; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar h3, |
||||||
|
div.sphinxsidebar h4 { |
||||||
|
font-family: 'Georgia', serif; |
||||||
|
color: #222; |
||||||
|
font-size: 1.2em; |
||||||
|
font-weight: normal; |
||||||
|
margin: 0; |
||||||
|
padding: 5px 10px; |
||||||
|
background-color: #ddd; |
||||||
|
text-shadow: 1px 1px 0 white |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar h4{ |
||||||
|
font-size: 1.1em; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar h3 a { |
||||||
|
color: #444; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
div.sphinxsidebar p { |
||||||
|
color: #555; |
||||||
|
padding: 5px 20px; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar p.topless { |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar ul { |
||||||
|
margin: 10px 20px; |
||||||
|
padding: 0; |
||||||
|
color: #000; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar a { |
||||||
|
color: #444; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar input { |
||||||
|
border: 1px solid #ccc; |
||||||
|
font-family: 'Georgia', serif; |
||||||
|
font-size: 1em; |
||||||
|
} |
||||||
|
|
||||||
|
div.sphinxsidebar input[type=text]{ |
||||||
|
margin-left: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
/* -- body styles ----------------------------------------------------------- */ |
||||||
|
|
||||||
|
a { |
||||||
|
color: #003B55; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
|
||||||
|
a:hover { |
||||||
|
color: #6D4100; |
||||||
|
text-decoration: underline; |
||||||
|
} |
||||||
|
|
||||||
|
div.body h1, |
||||||
|
div.body h2, |
||||||
|
div.body h3, |
||||||
|
div.body h4, |
||||||
|
div.body h5, |
||||||
|
div.body h6 { |
||||||
|
font-family: 'Georiga', serif; |
||||||
|
background-color: #bbb; |
||||||
|
font-weight: normal; |
||||||
|
color: #212224; |
||||||
|
margin: 30px 0px 10px 0px; |
||||||
|
padding: 8px 0 5px 10px; |
||||||
|
text-shadow: 0px 1px 0 white |
||||||
|
} |
||||||
|
|
||||||
|
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } |
||||||
|
div.body h2 { font-size: 150%; background-color: #ddd; } |
||||||
|
div.body h3 { font-size: 120%; background-color: #eee; } |
||||||
|
div.body h4 { font-size: 110%; background-color: #eee; } |
||||||
|
div.body h5 { font-size: 100%; background-color: #eee; } |
||||||
|
div.body h6 { font-size: 100%; background-color: #eee; } |
||||||
|
|
||||||
|
a.headerlink { |
||||||
|
color: #c60f0f; |
||||||
|
padding: 0 4px; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
|
||||||
|
a.headerlink:hover { |
||||||
|
background-color: #c60f0f; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li { |
||||||
|
line-height: 1.5em; |
||||||
|
} |
||||||
|
|
||||||
|
div.admonition p.admonition-title + p { |
||||||
|
display: inline; |
||||||
|
} |
||||||
|
|
||||||
|
div.highlight{ |
||||||
|
background-color: white; |
||||||
|
} |
||||||
|
|
||||||
|
div.note { |
||||||
|
background-color: #eee; |
||||||
|
border: 1px solid #ccc; |
||||||
|
} |
||||||
|
|
||||||
|
div.seealso { |
||||||
|
background-color: #ffc; |
||||||
|
border: 1px solid #ff6; |
||||||
|
} |
||||||
|
|
||||||
|
div.topic { |
||||||
|
background-color: #eee; |
||||||
|
} |
||||||
|
|
||||||
|
div.warning { |
||||||
|
background-color: #ffe4e4; |
||||||
|
border: 1px solid #f66; |
||||||
|
} |
||||||
|
|
||||||
|
p.admonition-title { |
||||||
|
display: inline; |
||||||
|
} |
||||||
|
|
||||||
|
p.admonition-title:after { |
||||||
|
content: ":"; |
||||||
|
} |
||||||
|
|
||||||
|
pre { |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
tt { |
||||||
|
background-color: #ecf0f3; |
||||||
|
color: #222; |
||||||
|
/* padding: 1px 2px; */ |
||||||
|
font-size: 1.1em; |
||||||
|
font-family: monospace; |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
[theme] |
||||||
|
inherit = basic |
||||||
|
stylesheet = flasky.css |
@ -0,0 +1,54 @@ |
|||||||
|
.. _becomingbig: |
||||||
|
|
||||||
|
Becoming Big |
||||||
|
============ |
||||||
|
|
||||||
|
Your application is becoming more and more complex? Flask is really not |
||||||
|
designed for large scale applications and does not attempt to do so, but |
||||||
|
that does not mean you picked the wrong tool in the first place. |
||||||
|
|
||||||
|
Flask is powered by Werkzeug and Jinja2, two libraries that are in use at |
||||||
|
a number of large websites out there and all Flask does is bringing those |
||||||
|
two together. Being a microframework, Flask is literally a single file. |
||||||
|
What that means for large applications is that it's probably a good idea |
||||||
|
to take the code from Flask and put it into a new module within the |
||||||
|
applications and expanding on that. |
||||||
|
|
||||||
|
What Could Be Improved? |
||||||
|
----------------------- |
||||||
|
|
||||||
|
For instance it makes a lot of sense to change the way endpoints (the |
||||||
|
names of the functions / URL rules) are handled to also take the module |
||||||
|
name into account. Right now the function name is the URL name, but |
||||||
|
imagine you have a large applications consisting of multiple components. |
||||||
|
In that case, it makes a lot of sense to use dotted names for the URL |
||||||
|
endpoints. |
||||||
|
|
||||||
|
Here some suggestions how Flask can be modified to better accomodate large |
||||||
|
scale applications: |
||||||
|
|
||||||
|
- implement dotted names for URL endpoints |
||||||
|
- get rid of the decorator function registering which causes a lot |
||||||
|
of troubles for applications that have circular dependencies. It |
||||||
|
also requires that the whole application is imported when the system |
||||||
|
initializes or certain URLs will not be available right away. |
||||||
|
- switch to explicit request object passing. This makes it more to type |
||||||
|
(because you now have something to pass around) but it makes it a |
||||||
|
whole lot easier to debug hairy situations and to test the code. |
||||||
|
- integrate the `Babel`_ i18n package or `SQLAlchemy`_ directl into the |
||||||
|
core framework. |
||||||
|
|
||||||
|
.. _Babel: http://babel.edgewall.org/ |
||||||
|
.. _SQLAlchemy: http://www.sqlalchemy.org/ |
||||||
|
|
||||||
|
Why does not Flask do all that by Default? |
||||||
|
------------------------------------------ |
||||||
|
|
||||||
|
There is a huge difference between a small application that only has to |
||||||
|
handle a couple of requests per second and with an overall code complexity |
||||||
|
of less than 4000 lines of code or something of larger scale. At one |
||||||
|
point it becomes important to integrate external systems, different |
||||||
|
storage backends and more. |
||||||
|
|
||||||
|
If Flask was designed with all these contingencies in mind, it would be a |
||||||
|
much more complex framework and less easy to get started with. |
@ -0,0 +1,96 @@ |
|||||||
|
# flasky extensions. flasky pygments style based on tango style |
||||||
|
from pygments.style import Style |
||||||
|
from pygments.token import Keyword, Name, Comment, String, Error, \ |
||||||
|
Number, Operator, Generic, Whitespace, Punctuation, Other, Literal |
||||||
|
|
||||||
|
|
||||||
|
class FlaskyStyle(Style): |
||||||
|
background_color = "#f8f8f8" |
||||||
|
default_style = "" |
||||||
|
|
||||||
|
styles = { |
||||||
|
# No corresponding class for the following: |
||||||
|
#Text: "", # class: '' |
||||||
|
Whitespace: "underline #f8f8f8", # class: 'w' |
||||||
|
Error: "#a40000 border:#ef2929", # class: 'err' |
||||||
|
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' |
||||||
|
|
||||||
|
Keyword: "bold #004461", # class: 'k' |
||||||
|
Keyword.Constant: "bold #004461", # class: 'kc' |
||||||
|
Keyword.Declaration: "bold #004461", # class: 'kd' |
||||||
|
Keyword.Namespace: "bold #004461", # class: 'kn' |
||||||
|
Keyword.Pseudo: "bold #004461", # class: 'kp' |
||||||
|
Keyword.Reserved: "bold #004461", # class: 'kr' |
||||||
|
Keyword.Type: "bold #004461", # class: 'kt' |
||||||
|
|
||||||
|
Operator: "#582800", # class: 'o' |
||||||
|
Operator.Word: "bold #004461", # class: 'ow' - like keywords |
||||||
|
|
||||||
|
Punctuation: "bold #000000", # class: 'p' |
||||||
|
|
||||||
|
# because special names such as Name.Class, Name.Function, etc. |
||||||
|
# are not recognized as such later in the parsing, we choose them |
||||||
|
# to look the same as ordinary variables. |
||||||
|
Name: "#000000", # class: 'n' |
||||||
|
Name.Attribute: "#c4a000", # class: 'na' - to be revised |
||||||
|
Name.Builtin: "#004461", # class: 'nb' |
||||||
|
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.Entity: "#ce5c00", # class: 'ni' |
||||||
|
Name.Exception: "bold #cc0000", # class: 'ne' |
||||||
|
Name.Function: "#000000", # class: 'nf' |
||||||
|
Name.Property: "#000000", # class: 'py' |
||||||
|
Name.Label: "#f57900", # class: 'nl' |
||||||
|
Name.Namespace: "#000000", # class: 'nn' - to be revised |
||||||
|
Name.Other: "#000000", # class: 'nx' |
||||||
|
Name.Tag: "bold #004461", # class: 'nt' - like a keyword |
||||||
|
Name.Variable: "#000000", # class: 'nv' - to be revised |
||||||
|
Name.Variable.Class: "#000000", # class: 'vc' - to be revised |
||||||
|
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' |
||||||
|
|
||||||
|
Literal: "#000000", # class: 'l' |
||||||
|
Literal.Date: "#000000", # class: 'ld' |
||||||
|
|
||||||
|
String: "#4e9a06", # class: 's' |
||||||
|
String.Backtick: "#4e9a06", # class: 'sb' |
||||||
|
String.Char: "#4e9a06", # class: 'sc' |
||||||
|
String.Doc: "italic #8f5902", # class: 'sd' - like a comment |
||||||
|
String.Double: "#4e9a06", # class: 's2' |
||||||
|
String.Escape: "#4e9a06", # class: 'se' |
||||||
|
String.Heredoc: "#4e9a06", # class: 'sh' |
||||||
|
String.Interpol: "#4e9a06", # class: 'si' |
||||||
|
String.Other: "#4e9a06", # class: 'sx' |
||||||
|
String.Regex: "#4e9a06", # class: 'sr' |
||||||
|
String.Single: "#4e9a06", # class: 's1' |
||||||
|
String.Symbol: "#4e9a06", # class: 'ss' |
||||||
|
|
||||||
|
Generic: "#000000", # class: 'g' |
||||||
|
Generic.Deleted: "#a40000", # class: 'gd' |
||||||
|
Generic.Emph: "italic #000000", # class: 'ge' |
||||||
|
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.Strong: "bold #000000", # class: 'gs' |
||||||
|
Generic.Subheading: "bold #800080", # class: 'gu' |
||||||
|
Generic.Traceback: "bold #a40000", # class: 'gt' |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
Foreword |
||||||
|
======== |
||||||
|
|
||||||
|
Read this before you get started with Flask. This hopefully answers some |
||||||
|
questions about the intention of the project, what it aims at and when you |
||||||
|
should or should not be using it. |
||||||
|
|
||||||
|
What does Micro Mean? |
||||||
|
--------------------- |
||||||
|
|
||||||
|
The micro in microframework for me means on the one hand being small in |
||||||
|
size, complexity but on the other hand also that the complexity of the |
||||||
|
applications that are written with these frameworks do not exceed a |
||||||
|
certain size. A microframework like Flask sacrifices a few things in |
||||||
|
order to be approachable and to be as concise as possible. |
||||||
|
|
||||||
|
For example Flask uses thread local objects internally so that you don't |
||||||
|
have to pass objects around from function to function within a request in |
||||||
|
order to stay threadsafe. While this is a really easy approach and saves |
||||||
|
you a lot of time, it also does not scale well to large applications. |
||||||
|
It's especially painful for more complex unittests and when you suddenly |
||||||
|
have to deal with code being executed outside of the context of a request |
||||||
|
(for example if you have cronjobs). |
||||||
|
|
||||||
|
Flask provides some tools to deal with the downsides of this approach but |
||||||
|
the core problem of this approach obviously stays. It is also based on |
||||||
|
convention over configuration which means that a lot of things are |
||||||
|
preconfigured in Flask and will work well for smaller applications but not |
||||||
|
so much for larger ones (where and how it looks for templates, static |
||||||
|
files etc.) |
||||||
|
|
||||||
|
But don't worry if your application suddenly grows larger than it was |
||||||
|
initially and you're afraid Flask might not grow with it. Even with |
||||||
|
larger frameworks you sooner or later will find out that you need |
||||||
|
something the framework just cannot do for you without modification. |
||||||
|
If you are ever in that situation, check out the :ref:`becomingbig` |
||||||
|
chapter. |
||||||
|
|
||||||
|
Target Audience |
||||||
|
--------------- |
||||||
|
|
||||||
|
Is Flask for you? Is your application small-ish (less than 4000 lines of |
||||||
|
Python code) and does not depend on too complex database structures, Flask |
||||||
|
is the Framework for you. It was designed from the ground up to be easy |
||||||
|
to use, based on established principles, good intentions and on top of two |
||||||
|
established libraries in widespread usage. |
||||||
|
|
||||||
|
Flask serves two purposes: it's an example of how to create a minimal and |
||||||
|
opinionated framework on top of Werkzeug to show how this can be done, and |
||||||
|
to provide people with a simple tool to prototype larger applications or |
||||||
|
to implement small and medium sized applications. |
||||||
|
|
||||||
|
If you suddenly discover that your application grows larger than |
||||||
|
originally intended, head over to the :ref:`becomingbig` section to see |
||||||
|
some possible solutions for larger applications. |
||||||
|
|
||||||
|
Satisfied? Then head over to the :ref:`installation`. |
Loading…
Reference in new issue