Browse files

And finished documentation for most parts.

  • Loading branch information...
1 parent 4edec48 commit 727c701686c18c4a27ca523eb0c5862d497be24e @mitsuhiko mitsuhiko committed Apr 9, 2010
Showing with 199 additions and 4 deletions.
  1. +2 −0 docs/api.rst
  2. +7 −3 docs/index.rst
  3. +166 −0 docs/patterns.rst
  4. +23 −0 docs/quickstart.rst
  5. +1 −1 examples/minitwit/minitwit.py
View
2 docs/api.rst
@@ -1,3 +1,5 @@
+.. _api:
+
API
===
View
10 docs/index.rst
@@ -1,13 +1,17 @@
Welcome to Flask
================
-Welcome to Flask's documentation.
-
-Contents:
+Welcome to Flask's documentation. This documentation is devided into
+different parts. I would suggest to get started with the
+:ref:`installation` and then heading over to the :ref:`quickstart`. If
+you want to dive into all the internal parts of Flask, check out the
+:ref:`api` documentation. Common patterns are described in the
+:ref:`patterns` section.
.. toctree::
:maxdepth: 2
installation
quickstart
+ patterns
api
View
166 docs/patterns.rst
@@ -0,0 +1,166 @@
+.. _patterns:
+
+Patterns in Flask
+=================
+
+Certain things are common enough that the changes are high you will find
+them in most web applications. For example quite a lot of applications
+are using relational databases and user authentication. In that case,
+changes are they will open a database connection at the beginning of the
+request and get the information of the currently logged in user. At the
+end of the request, the database connection is closed again.
+
+In Flask you can implement such things with the
+:meth:`~flask.Flask.request_init` and
+:meth:`~flask.Flask.request_shutdown` decorators in combination with the
+special :class:`~flask.g` object.
+
+
+Using SQLite 3 with Flask
+-------------------------
+
+So here a simple example how you can use SQLite 3 with Flask::
+
+ import sqlite3
+ from flask import g
+
+ DATABASE = '/path/to/database.db'
+
+ def connect_db():
+ return sqlite3.connect(DATABASE)
+
+ @app.request_init
+ def before_request():
+ g.db = connect_db()
+
+ @app.request_shutdown
+ def after_request(response):
+ g.db.close()
+ return response
+
+Easy Querying
+`````````````
+
+Now in each request handling function you can access `g.db` to get the
+current open database connection. To simplify working with SQLite a
+helper function can be useful::
+
+ def query_db(query, args=(), one=False):
+ cur = g.db.execute(query, args)
+ rv = [dict((cur.description[idx][0], value)
+ for idx, value in enumerate(row)) for row in cur.fetchall()]
+ return (rv[0] if rv else None) if one else rv
+
+This handy little function 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::
+
+ for user in query_db('select * from users'):
+ print user['username'], 'has the id', user['user_id']
+
+Or if you just want a single result::
+
+ user = query_db('select * from users where username = ?',
+ [the_username], one=True)
+ if user is None:
+ print 'No such user'
+ else:
+ print the_username, 'has the id', user['user_id']
+
+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 formattings because this makes it possible
+to attack the application using `SQL Injections
+<http://en.wikipedia.org/wiki/SQL_injection>`_.
+
+Initial Schemas
+```````````````
+
+Relational databases need schemas, so applications often ship a
+`schema.sql` file that creates the database. It's a good idea to provide
+a function that creates the database bases on that schema. This function
+can do that for you::
+
+ from contextlib import closing
+
+ def init_db():
+ with closing(connect_db()) as db:
+ with app.open_resource('schema.sql') as f:
+ db.cursor().executescript(f.read())
+ db.commit()
+
+You can then create such a database from the python shell:
+
+>>> from yourapplication import init_db
+>>> init_db()
+
+.. _template-inheritance:
+
+Template Inheritance
+--------------------
+
+The most powerful part of Jinja is template inheritance. Template inheritance
+allows you to build a base "skeleton" template that contains all the common
+elements of your site and defines **blocks** that child templates can override.
+
+Sounds complicated but is very basic. It's easiest to understand it by starting
+with an example.
+
+
+Base Template
+`````````````
+
+This template, which we'll call ``layout.html``, defines a simple HTML skeleton
+document that you might use for a simple two-column page. It's the job of
+"child" templates to fill the empty blocks with content:
+
+.. sourcecode:: html+jinja
+
+ <!doctype html>
+ <html>
+ <head>
+ {% block head %}
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
+ <title>{% block title %}{% endblock %} - My Webpage</title>
+ {% endblock %}
+ </head>
+ <body>
+ <div id="content">{% block content %}{% endblock %}</div>
+ <div id="footer">
+ {% block footer %}
+ &copy; Copyright 2010 by <a href="http://domain.invalid/">you</a>.
+ {% endblock %}
+ </div>
+ </body>
+
+In this example, the ``{% block %}`` tags define four blocks that child templates
+can fill in. All the `block` tag does is to tell the template engine that a
+child template may override those portions of the template.
+
+Child Template
+``````````````
+
+A child template might look like this:
+
+.. sourcecode:: html+jinja
+
+ {% extends "layout.html" %}
+ {% block title %}Index{% endblock %}
+ {% block head %}
+ {{ super() }}
+ <style type="text/css">
+ .important { color: #336699; }
+ </style>
+ {% endblock %}
+ {% block content %}
+ <h1>Index</h1>
+ <p class="important">
+ Welcome on my awesome homepage.
+ {% endblock %}
+
+The ``{% extends %}`` tag is the key here. It tells the template engine that
+this template "extends" another template. When the template system evaluates
+this template, first it locates the parent. The extends tag must be the
+first tag in the template. To render the contents of a block defined in
+the parent template, use ``{{ super() }}``.
View
23 docs/quickstart.rst
@@ -1,3 +1,5 @@
+.. _quickstart:
+
Quickstart
==========
@@ -148,6 +150,22 @@ don't have to deal with that. It will also make sure that ``HEAD``
requests are handled like the RFC demands, so you can completely ignore
that part of the HTTP specification.
+Static Files
+------------
+
+Dynamic web applications need static files as well. That's usually where
+the CSS and JavaScript files are coming from. Ideally your web server is
+configured to serve them for you, but during development Flask can do that
+as well. Just create a folder called `static` in your package or next to
+your module and it will be available at `/static` on the application.
+
+To generate URLs to that part of the URL, use the special ``'static'`` URL
+name::
+
+ url_for('static', filename='style.css')
+
+The file has to be stored on the filesystem as ``static/style.css``.
+
Rendering Templates
-------------------
@@ -205,6 +223,11 @@ Inside templates you also have access to the :class:`~flask.request`,
:class:`~flask.session` and :class:`~flask.g` objects as well as the
:func:`~flask.get_flashed_messages` function.
+Templates are especially useful if inheritance is used. If you want to
+know how that works, head over to the :ref:`template-inheritance` pattern
+documentation. Basically template inheritance makes it possible to keep
+certain elements on each page (like header, navigation and footer).
+
Automatic escaping is enabled, so if name contains HTML it will be escaped
automatically. If you can trust a variable and you know that it will be
safe HTML (because for example it came from a module that converts wiki
View
2 examples/minitwit/minitwit.py
@@ -65,7 +65,7 @@ def before_request():
"""Make sure we are connected to the database each request and look
up the current user so that we know he's there.
"""
- g.db = sqlite3.connect(DATABASE)
+ g.db = connect_db()
if 'user_id' in session:
g.user = query_db('select * from user where user_id = ?',
[session['user_id']], one=True)

0 comments on commit 727c701

Please sign in to comment.