Skip to content

Commit

Permalink
Restructured documentation a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Apr 16, 2010
1 parent fb2d2e4 commit 26f86b1
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 8 deletions.
32 changes: 30 additions & 2 deletions docs/index.rst
Expand Up @@ -14,15 +14,43 @@ you rather 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.

Flask also depends on two external libraries: the `Jinja2`_ template
engine and the `Werkzeug`_ WSGI toolkit. both of which are not documented
here. If you want to dive into their documentation check out the
following links:

- `Jinja2 Documentation <http://jinja.pocoo.org/2/documentation/>`_
- `Werkzeug Documentation <http://werkzeug.pocoo.org/documentation/>`_

.. _Jinja2: http://jinja.pocoo.org/2/
.. _Werkzeug: http://werkzeug.pocoo.org/

Textual Documentation
---------------------

This part of the documentation is written text and should give you an idea
how to work with Flask. It's a series of step-by-step instructions for
web development.

.. toctree::
:maxdepth: 2

foreword
installation
quickstart
tutorial
testing
patterns
api
deploying
testing
becomingbig

Reference
---------

If you are looking for information on a specific function, class or
method, this part of the documentation is for you:

.. toctree::
:maxdepth: 2

api
189 changes: 183 additions & 6 deletions docs/patterns.rst
@@ -1,7 +1,7 @@
.. _patterns:

Patterns in Flask
=================
Patterns for 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
Expand All @@ -10,17 +10,105 @@ 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.before_request` and
:meth:`~flask.Flask.after_request` decorators in combination with the
special :class:`~flask.g` object.

.. _larger-applications:

Larger Applications
-------------------

For larger applications it's a good idea to use a package instead of a
module. That is quite simple. Imagine a small application looks like
this::

/yourapplication
/yourapplication.py
/static
/style.css
/templates
layout.html
index.html
login.html
...

To convert that into a larger one, just create a new folder
`yourapplication` inside the existing one and move everything below it.
Then rename `yourapplication.py` to `__init__.py`. (Make sure to delete
all `.pyc` files first, otherwise things would most likely break)

You should then end up with something like that::

/yourapplication
/yourapplication
/__init__.py
/static
/style.css
/templates
layout.html
index.html
login.html
...

But how do you run your application now? The naive ``python
yourapplication/__init__.py`` will not work. Let's just say that Python
does not want modules in packages to be the startup file. But that is not
a big problem, just add a new file called `runserver.py` next to the inner
`yourapplication` folder with the following contents::

from yourapplication import app
app.run(debug=True)

What did we gain from this? Now we can restructure the application a bit
into multiple modules. The only thing you have to remember is the
following quick checklist:

1. the `Flask` application object creation have to be in the
`__init__.py` file. That way each module can import it safely and the
`__name__` variable will resole to the correct package.
2. all the view functions (the ones with a :meth:`~flask.Flask.route`
decorator on top) have to be imported when in the `__init__.py` file.
Not the objects itself, but the module it is in. Do the importing at
the *bottom* of the file.

Here an example `__init__.py`::

from flask import Flask
app = Flask(__name__)

import yourapplication.views

And this is what `views.py` would look like::

from yourapplication import app

@app.route('/')
def index():
return 'Hello World!'

.. admonition:: Circular Imports

Every Python programmer hates it, and yet we just did that: circular
imports (That's when one module depends on another one. In this case
`views.py` depends on `__init__.py`). Be advised that this is a bad
idea in general but here it is actually fine. The reason for this is
that we are not actually using the views in `__init__.py` and just
ensuring the module is imported and we are doing that at the bottom of
the file.

There are still some problems with that approach but if you want to use
decorators there is no way around that. Check out the
:ref:`becomingbig` section for some inspiration how to deal with that.


.. _database-pattern:

Using SQLite 3 with Flask
-------------------------

In Flask you can implement opening of dabase connections at the beginning
of the request and closing at the end with the
:meth:`~flask.Flask.before_request` and :meth:`~flask.Flask.after_request`
decorators in combination with the special :class:`~flask.g` object.

So here a simple example how you can use SQLite 3 with Flask::

import sqlite3
Expand Down Expand Up @@ -99,6 +187,95 @@ You can then create such a database from the python shell:
>>> from yourapplication import init_db
>>> init_db()


.. _sqlalchemy-pattern:

SQLAlchemy in Flask
-------------------

Many people prefer `SQLAlchemy`_ for database access. In this case it's
encouraged to use a package instead of a module for your flask application
and drop the modules into a separate module (:ref:`larger-applications`).
Although that is not necessary but makes a lot of sense.

There are three very common ways to use SQLAlchemy. I will outline each
of them here:

Declarative
```````````

The declarative extension in SQLAlchemy is the most recent method of using
SQLAlchemy. It allows you to define tables and models in one go, similar
to how Django works. In addition to the following text I recommend the
official documentation on the `declarative`_ extension.

Here the example `database.py` module for your application::

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db')
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
Base.metadata.create_all(bind=engine)

To define your models, subclass the `Base` class the above code generated.

To use SQLAlchemy in a declarative way with your application, you just
have to put the following code into your application module Flask will
automatically remove database sessions at the end of the request for you::

from yourapplication.database import db_session

@app.after_request
def shutdown_session(response):
db_session.remove()
return response

Here an example model (put that into `models.py` for instance)::

from sqlalchemy import Column, Integer, String
from yourapplication.database import Base

class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True)
email = Column(String(120), unique=True)

def __init__(self, name=None, email=None):
self.name = name
self.email = email

def __repr__(self):
return '<User %r>' % (self.name, self.email)

You can insert entries into the database like this then:

>>> from yourapplication.database import db_session
>>> from yourapplication.models import User
>>> u = User('admin', 'admin@localhost')
>>> db_session.add(u)
>>> db_session.commit()

Querying is simple as well:

>>> User.query.all()
[<User u'admin'>]
>>> User.query.filter(User.name == 'admin').first()
<User u'admin'>

.. _SQLAlchemy: http://www.sqlalchemy.org/
.. _declarative:
http://www.sqlalchemy.org/docs/reference/ext/declarative.html


.. _template-inheritance:

Template Inheritance
Expand Down

0 comments on commit 26f86b1

Please sign in to comment.