Sophie

Sophie

distrib > Fedora > 14 > i386 > media > os > by-pkgid > 5c4f8358fd6fdc210fb0d926bd25802c > files > 265

python-werkzeug-doc-0.6.2-2.fc14.noarch.rpm


<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Werkzeug Documentation</title>
    <link rel="stylesheet" href="_static/style.css" type="text/css">
    <link rel="stylesheet" href="_static/print.css" type="text/css" media="print">
    <link rel="stylesheet" href="_static/pygments.css" type="text/css">
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:   '#',
        VERSION:    '0.6.1'
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/interface.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <script type="text/javascript" src="_static/werkzeug.js"></script>
    <link rel="contents" title="Global table of contents" href="contents.html">
    <link rel="index" title="Global index" href="genindex.html">
    <link rel="search" title="Search" href="search.html">
    <link rel="top" title="Werkzeug v0.6.1 documentation" href="index.html">
    <link rel="next" title="API Levels" href="levels.html">
    <link rel="prev" title="Installation" href="installation.html">
    
  </head>
  <body>
    <div class="page">
      <div class="header">
        <h1 class="heading"><a href="index.html"
          title="back to the documentation overview"><span>Werkzeug</span></a></h1>
      </div>
      <ul class="navigation">
        <li class="indexlink"><a href="index.html">Overview</a></li>
        <li><a href="installation.html">&laquo; Installation</a></li>
        <li class="active"><a href="#">Werkzeug Tutorial</a></li>
        <li><a href="levels.html">API Levels &raquo;</a></li>
      </ul>
      <div class="body">
        <div id="toc">
          <h3>Table Of Contents</h3>
          <div class="inner"><ul>
<li><a class="reference external" href="#">Werkzeug Tutorial</a><ul>
<li><a class="reference external" href="#part-0-the-folder-structure">Part 0: The Folder Structure</a></li>
<li><a class="reference external" href="#part-1-the-wsgi-application">Part 1: The WSGI Application</a></li>
<li><a class="reference external" href="#part-2-the-utilities">Part 2: The Utilities</a></li>
<li><a class="reference external" href="#intermission-and-now-for-something-completely-different">Intermission: And Now For Something Completely Different</a></li>
<li><a class="reference external" href="#part-3-database-models">Part 3: Database Models</a></li>
<li><a class="reference external" href="#part-4-the-view-functions">Part 4: The View Functions</a></li>
<li><a class="reference external" href="#part-5-the-templates">Part 5: The Templates</a></li>
<li><a class="reference external" href="#intermission-adding-the-design">Intermission: Adding The Design</a></li>
<li><a class="reference external" href="#part-6-listing-public-urls">Part 6: Listing Public URLs</a></li>
<li><a class="reference external" href="#the-end-result">The End Result</a></li>
<li><a class="reference external" href="#bonus-styling-404-error-pages">Bonus: Styling 404 Error Pages</a></li>
<li><a class="reference external" href="#outro">Outro</a></li>
</ul>
</li>
</ul>
</div>
        </div>
        
  <div class="section" id="module-werkzeug">
<span id="werkzeug-tutorial"></span><h1>Werkzeug Tutorial<a class="headerlink" href="#module-werkzeug" title="Permalink to this headline">¶</a></h1>
<p>Welcome to the Werkzeug 0.5 tutorial in which we will create a <a class="reference external" href="http://tinyurl.com/">TinyURL</a> clone
that stores URLs in a database.  The libraries we will use for this
applications are <a class="reference external" href="http://jinja.pocoo.org/">Jinja</a> 2 for the templates, <a class="reference external" href="http://sqlalchemy.org/">SQLAlchemy</a> for the database
layer and, of course, Werkzeug for the WSGI layer.</p>
<p>The reasons why we&#8217;ve decided on these libraries for the tutorial application
is that we want to stick to some of the design decisions <a class="reference external" href="http://www.djangoproject.com/">Django</a> took in the
past.  One of them is using view functions instead of controller classes with
action methods, which is common in <a class="reference external" href="http://www.rubyonrails.org/">Rails</a> and <a class="reference external" href="http://pylonshq.com/">Pylons</a>, the other one is
designer-friendly templates.</p>
<p>The Werkzeug <a class="reference external" href="http://dev.pocoo.org/projects/werkzeug/browser/examples">example folder</a> contains a couple of applications that use other
template engines, too, so you may want to have a look at them.  There is also
the source code of this application.</p>
<p>You can use <a class="reference external" href="http://peak.telecommunity.com/DevCenter/EasyInstall">easy_install</a> to install the required libraries:</p>
<div class="highlight-python"><pre>sudo easy_install Jinja2
sudo easy_install SQLAlchemy</pre>
</div>
<p>If you&#8217;re on Windows, omit the &#8220;sudo&#8221; (and make sure, <a class="reference external" href="http://pypi.python.org/pypi/setuptools">setuptools</a> is
installed); if you&#8217;re on OS X, you can check if the libraries are also
available in port; or on Linux, you can check out your package manager for
packages called <tt class="docutils literal"><span class="pre">python-jinja2</span></tt> and <tt class="docutils literal"><span class="pre">python-sqlalchemy</span></tt>.</p>
<p>If you&#8217;re curious, check out the <a class="reference external" href="http://werkzeug.pocoo.org/e/shorty/">online demo</a> of the application.</p>
<div class="section" id="part-0-the-folder-structure">
<h2>Part 0: The Folder Structure<a class="headerlink" href="#part-0-the-folder-structure" title="Permalink to this headline">¶</a></h2>
<p>Before we can get started we have to create a Python package for our Werkzeug
application and the folders for the templates and static files.</p>
<p>This tutorial application is called <cite>shorty</cite> and the initial directory layout
we will use looks like this:</p>
<div class="highlight-python"><pre>manage.py
shorty/
    __init__.py
    templates/
    static/</pre>
</div>
<p>The <tt class="docutils literal"><span class="pre">__init__.py</span></tt> and <tt class="docutils literal"><span class="pre">manage.py</span></tt> files should be empty for the time
being.   The first one makes <tt class="docutils literal"><span class="pre">shorty</span></tt> a Python package, the second one will
hold our management utilities later.</p>
</div>
<div class="section" id="part-1-the-wsgi-application">
<h2>Part 1: The WSGI Application<a class="headerlink" href="#part-1-the-wsgi-application" title="Permalink to this headline">¶</a></h2>
<p>Unlike Django or other frameworks, Werkzeug operates directly on the WSGI
layer.  There is no fancy magic that implements the central WSGI application
for you.  As a result of that the first thing you will do every time you write
a Werkzeug application is implementing this basic WSGI application object.
This can now either be a function or, even better, a callable class.</p>
<p>A callable class has huge advantages over a function.  For one you can pass
it some configuration parameters and furthermore you can use inline WSGI
middlewares.  Inline WSGI middlewares are basically middlewares applied
&#8220;inside&#8221; of our application object.  This is a good idea for middlewares that
are essential for the application (session middlewares, serving of media
files etc.).</p>
<p>Here the initial code for our <tt class="docutils literal"><span class="pre">shorty/application.py</span></tt> file which implements
the WSGI application:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">create_engine</span>
<span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">Request</span><span class="p">,</span> <span class="n">ClosingIterator</span>
<span class="kn">from</span> <span class="nn">werkzeug.exceptions</span> <span class="kn">import</span> <span class="n">HTTPException</span>

<span class="kn">from</span> <span class="nn">shorty.utils</span> <span class="kn">import</span> <span class="n">session</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">local</span><span class="p">,</span> <span class="n">local_manager</span><span class="p">,</span> <span class="n">url_map</span>
<span class="kn">from</span> <span class="nn">shorty</span> <span class="kn">import</span> <span class="n">views</span>
<span class="kn">import</span> <span class="nn">shorty.models</span>


<span class="k">class</span> <span class="nc">Shorty</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db_uri</span><span class="p">):</span>
        <span class="n">local</span><span class="o">.</span><span class="n">application</span> <span class="o">=</span> <span class="bp">self</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">database_engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="n">db_uri</span><span class="p">,</span> <span class="n">convert_unicode</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">init_database</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">database_engine</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
        <span class="n">local</span><span class="o">.</span><span class="n">application</span> <span class="o">=</span> <span class="bp">self</span>
        <span class="n">request</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
        <span class="n">local</span><span class="o">.</span><span class="n">url_adapter</span> <span class="o">=</span> <span class="n">adapter</span> <span class="o">=</span> <span class="n">url_map</span><span class="o">.</span><span class="n">bind_to_environ</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span> <span class="o">=</span> <span class="n">adapter</span><span class="o">.</span><span class="n">match</span><span class="p">()</span>
            <span class="n">handler</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">views</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">)</span>
            <span class="n">response</span> <span class="o">=</span> <span class="n">handler</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="o">**</span><span class="n">values</span><span class="p">)</span>
        <span class="k">except</span> <span class="n">HTTPException</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
            <span class="n">response</span> <span class="o">=</span> <span class="n">e</span>
        <span class="k">return</span> <span class="n">ClosingIterator</span><span class="p">(</span><span class="n">response</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">),</span>
                               <span class="p">[</span><span class="n">session</span><span class="o">.</span><span class="n">remove</span><span class="p">,</span> <span class="n">local_manager</span><span class="o">.</span><span class="n">cleanup</span><span class="p">])</span>
</pre></div>
</div>
<p>That&#8217;s a lot of code for the beginning!  Let&#8217;s go through it step by step.
First we have a couple of imports:  From SQLAlchemy we import a factory
function that creates a new database engine for us.  A database engine holds
a pool of connections for us and manages them.  The next few imports pull some
objects into the namespace Werkzeug provides: a request object, a special
iterator class that helps us cleaning up stuff at the request end and finally
the base class for all HTTP exceptions.</p>
<p>The next five imports are not working because we don&#8217;t have the utils module
written yet.  However we should cover some of the objects already.  The
<cite>session</cite> object pulled from there is not a PHP-like session object but a
SQLAlchemy database session object.  Basically a database session object keeps
track of yet uncommited objects for the database.  Unlike Django, an
instantiated SQLAlchemy model is already tracked by the session!  The metadata
object is also an SQLAlchemy thing which is used to keep track of tables.  We
can use the metadata object to easily create all tables for the database and
SQLAlchemy uses it to look up foreign keys and similar stuff.</p>
<p>The <cite>local</cite> object is basically a thread local object created in the utility
module for us.  Every attribute on this object is bound to the current request
and we can use this to implicitly pass objects around in a thread-safe way.</p>
<p>The <cite>local_manager</cite> object ensures that all local objects it keeps track of
are properly deleted at the end of the request.</p>
<p>The last thing we import from there is the URL map which holds the URL routing
information.  If you know Django you can compare that to the url patterns you
specify in the <tt class="docutils literal"><span class="pre">urls.py</span></tt> module, if you have used PHP so far it&#8217;s comparable
with some sort of built-in &#8220;mod_rewrite&#8221;.</p>
<p>We import our views module which holds the view functions and then we import
the models module which holds all of our models.  Even if it looks like we
don&#8217;t use that import it&#8217;s there so that all the tables are registered on the
metadata properly.</p>
<p>So let&#8217;s have a look at the application class.  The constructor of this class
takes a database URI which is basically the type of the database and the login
credentials or location of the database.  For SQLite this is for example
<tt class="docutils literal"><span class="pre">'sqlite:////tmp/shorty.db'</span></tt> (note that these are <strong>four</strong> slashes).</p>
<p>In the constructor we create a database engine for that database URI and use
the <cite>convert_unicode</cite> parameter to tell SQLAlchemy that our strings are all
unicode objects.</p>
<p>Another thing we do here is binding the application to the local object.  This
is not really required but useful if we want to play with the application in
a python shell.  On application instanciation we have it bound to the current
thread and all the database functions will work as expected.  If we don&#8217;t do
that Werkzeug will complain that it&#8217;s unable to find the database when it&#8217;s
creating a session for SQLAlchemy.</p>
<p>The <cite>init_database</cite> function defined below can be used to create all the
tables we use.</p>
<p>And then comes the request dispatching function.  In there we create a new
request object by passing the environment to the <a title="werkzeug.Request" class="reference external" href="wrappers.html#werkzeug.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a> constructor.
Once again we bind the application to the local object, this time, however,
we have to do this, otherwise things will break soon.</p>
<p>Then we create a new URL map adapter by binding the URL map to the current
WSGI environment.  This basically looks at the environment of the incoming
request information and fetches the information from the environment it
requires.  This is for example the name of the server for external URLs, the
location of the script so that it can generate absolute paths if we use the
URL builder.  We also bind the adapter to the local object so that we can
use it for URL generation in the utils module.</p>
<p>After that we have a <cite>try</cite>/<cite>except</cite> that catches HTTP exceptions that could
occur while matching or in the view function.  When the adapter does not find
a valid endpoint for our current request it will raise a <a title="werkzeug.exceptions.NotFound" class="reference external" href="exceptions.html#werkzeug.exceptions.NotFound"><tt class="xref py py-exc docutils literal"><span class="pre">NotFound</span></tt></a>
exception which we can use like a response object.  An endpoint is basically
the name of the function we want to handle our request with.  We just get the
function with the name of the endpoint and pass it the request and the URL
values.</p>
<p>At the end of the function we call the response object as WSGI application
and pass the return value of this function (which will be an iterable) to
the closing iterator class along with our cleanup callbacks (which remove
the current SQLAlchemy session and clean up the data left in the local
objects).</p>
<p>As next step create two empty files <tt class="docutils literal"><span class="pre">shorty/views.py</span></tt> and
<tt class="docutils literal"><span class="pre">shorty/models.py</span></tt> so that our imports work.  We will fill the modules with
useful code later.</p>
</div>
<div class="section" id="part-2-the-utilities">
<h2>Part 2: The Utilities<a class="headerlink" href="#part-2-the-utilities" title="Permalink to this headline">¶</a></h2>
<p>Now we have basically finished the WSGI application itself but we have to add
some more code into our utiliy module so that the imports work.  For the time
being we just add the objects which we need for the application to work.  All
the following code goes into the <tt class="docutils literal"><span class="pre">shorty/utils.py</span></tt> file:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">MetaData</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">create_session</span><span class="p">,</span> <span class="n">scoped_session</span>
<span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">Local</span><span class="p">,</span> <span class="n">LocalManager</span>
<span class="kn">from</span> <span class="nn">werkzeug.routing</span> <span class="kn">import</span> <span class="n">Map</span><span class="p">,</span> <span class="n">Rule</span>

<span class="n">local</span> <span class="o">=</span> <span class="n">Local</span><span class="p">()</span>
<span class="n">local_manager</span> <span class="o">=</span> <span class="n">LocalManager</span><span class="p">([</span><span class="n">local</span><span class="p">])</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">local</span><span class="p">(</span><span class="s">&#39;application&#39;</span><span class="p">)</span>

<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span>
<span class="n">session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">create_session</span><span class="p">(</span><span class="n">application</span><span class="o">.</span><span class="n">database_engine</span><span class="p">,</span>
                         <span class="n">autocommit</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">autoflush</span><span class="o">=</span><span class="bp">False</span><span class="p">),</span>
                         <span class="n">local_manager</span><span class="o">.</span><span class="n">get_ident</span><span class="p">)</span>

<span class="n">url_map</span> <span class="o">=</span> <span class="n">Map</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">expose</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">decorate</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
        <span class="n">kw</span><span class="p">[</span><span class="s">&#39;endpoint&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">__name__</span>
        <span class="n">url_map</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Rule</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">f</span>
    <span class="k">return</span> <span class="n">decorate</span>

<span class="k">def</span> <span class="nf">url_for</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">_external</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="o">**</span><span class="n">values</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">local</span><span class="o">.</span><span class="n">url_adapter</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">force_external</span><span class="o">=</span><span class="n">_external</span><span class="p">)</span>
</pre></div>
</div>
<p>First we again import a bunch of stuff, then we create the local objects and
the local manager we already discussed in the section above.  The new thing
here is that calling a local object with a string returns a proxy object.  This
returned proxy object always points to the attribute with that name on the
local object.  For example <cite>application</cite> now points to <cite>local.application</cite>
all the time.  If you, however, try to do something with it and there is
no object bound to <cite>local.application</cite> you will get a <tt class="xref py py-exc docutils literal"><span class="pre">RuntimeError</span></tt>.</p>
<p>The next three lines are basically everything we need to get SQLAlchemy 0.4
or higher running in a Werkzeug application.  We create a new metadata for all
of our tables and then a new scoped session using the <cite>scoped_session</cite> factory
function.  This basically tells SQLAlchemy to use the same algorithm to
determine the current context as werkzeug local does and use the database
engine of the current application.</p>
<p>If we don&#8217;t plan to add support for multiple instances of the application in
the same python interpreter we can also simplify that code by not looking up
the application on the current local object but somewhere else.  This approach
is for example used by Django but makes it impossible to combine multiple such
applications.</p>
<p>The rest of the module is code we will use in our views.  Basically the idea
there is to use decorators to specify the URL dispatching rule for a view
function rather than a central <tt class="docutils literal"><span class="pre">urls.py</span></tt> file like you could do in Django
or a <tt class="docutils literal"><span class="pre">.htaccess</span></tt> for URL rewrites like you would do in PHP.  This is
<strong>one</strong> way to do it and there are countless of other ways to handle rule
definitions.</p>
<p>The <cite>url_for</cite> function, which we have there too, provides a simple way to
generate URLs by endpoint.  We will use it in the views and our model later.</p>
</div>
<div class="section" id="intermission-and-now-for-something-completely-different">
<h2>Intermission: And Now For Something Completely Different<a class="headerlink" href="#intermission-and-now-for-something-completely-different" title="Permalink to this headline">¶</a></h2>
<p>Now that we have finished the foundation for the application we could relax
and do something completely different: management scripts.  Most of the time
you do similar tasks while developing.  One of them is firing up a
development server (If you&#8217;re used to PHP: Werkzeug does not rely on Apache
for development, it&#8217;s perfectly fine and also recommended to use the wsgiref
server that comes with python for development purposes), starting a python
interpreter to play with the database models, initializing the database etc.</p>
<p>Werkzeug makes it incredible easy to write such management scripts.  The
following piece of code implements a fully featured management script.  Put
it into the <cite>manage.py</cite> file you have created in the beginning:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
<span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">script</span>

<span class="k">def</span> <span class="nf">make_app</span><span class="p">():</span>
    <span class="kn">from</span> <span class="nn">shorty.application</span> <span class="kn">import</span> <span class="n">Shorty</span>
    <span class="k">return</span> <span class="n">Shorty</span><span class="p">(</span><span class="s">&#39;sqlite:////tmp/shorty.db&#39;</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">make_shell</span><span class="p">():</span>
    <span class="kn">from</span> <span class="nn">shorty</span> <span class="kn">import</span> <span class="n">models</span><span class="p">,</span> <span class="n">utils</span>
    <span class="n">application</span> <span class="o">=</span> <span class="n">make_app</span><span class="p">()</span>
    <span class="k">return</span> <span class="nb">locals</span><span class="p">()</span>

<span class="n">action_runserver</span> <span class="o">=</span> <span class="n">script</span><span class="o">.</span><span class="n">make_runserver</span><span class="p">(</span><span class="n">make_app</span><span class="p">,</span> <span class="n">use_reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">action_shell</span> <span class="o">=</span> <span class="n">script</span><span class="o">.</span><span class="n">make_shell</span><span class="p">(</span><span class="n">make_shell</span><span class="p">)</span>
<span class="n">action_initdb</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">make_app</span><span class="p">()</span><span class="o">.</span><span class="n">init_database</span><span class="p">()</span>

<span class="n">script</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p><a class="reference external" href="script.html#module-werkzeug.script"><tt class="xref py py-mod docutils literal"><span class="pre">werkzeug.script</span></tt></a> is explained in detail in the script documentation
and we won&#8217;t cover it here, most of the code should be self explaining anyway.</p>
<p>What&#8217;s important is that you should be able to run <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">shell</span></tt>
to get an interactive Python interpreter without traceback.  If you get an
exception check the line number and compare your code with the code we have
in the code boxes above.  Also make sure that you have created the empty
<tt class="docutils literal"><span class="pre">shorty/views.py</span></tt> and <tt class="docutils literal"><span class="pre">shorty/models.py</span></tt> files.</p>
<p>To run your application for development purposes you can also use the manage
script.  Just execute this command from your command line:</p>
<div class="highlight-python"><pre>python manage.py runserver</pre>
</div>
<p>The server will then listen on <a class="reference external" href="http://localhost:5000/">localhost:5000</a>
for incoming requests and show your application.  But we need to implement
some more things before we can run the server without errors.</p>
<p>Now that the script system is running we can start writing our database models.</p>
</div>
<div class="section" id="part-3-database-models">
<h2>Part 3: Database Models<a class="headerlink" href="#part-3-database-models" title="Permalink to this headline">¶</a></h2>
<p>Now we can create the models.  Because the application is pretty simple we
just have one model and table:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
<span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Boolean</span><span class="p">,</span> <span class="n">DateTime</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">mapper</span>
<span class="kn">from</span> <span class="nn">shorty.utils</span> <span class="kn">import</span> <span class="n">session</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">url_for</span><span class="p">,</span> <span class="n">get_random_uid</span>

<span class="n">url_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;urls&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
    <span class="n">Column</span><span class="p">(</span><span class="s">&#39;uid&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">140</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
    <span class="n">Column</span><span class="p">(</span><span class="s">&#39;target&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">500</span><span class="p">)),</span>
    <span class="n">Column</span><span class="p">(</span><span class="s">&#39;added&#39;</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">),</span>
    <span class="n">Column</span><span class="p">(</span><span class="s">&#39;public&#39;</span><span class="p">,</span> <span class="n">Boolean</span><span class="p">)</span>
<span class="p">)</span>

<span class="k">class</span> <span class="nc">URL</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">query</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="n">query_property</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">public</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">uid</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">added</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">public</span> <span class="o">=</span> <span class="n">public</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">added</span> <span class="o">=</span> <span class="n">added</span> <span class="ow">or</span> <span class="n">datetime</span><span class="o">.</span><span class="n">utcnow</span><span class="p">()</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">uid</span><span class="p">:</span>
            <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
                <span class="n">uid</span> <span class="o">=</span> <span class="n">get_random_uid</span><span class="p">()</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">uid</span><span class="p">):</span>
                    <span class="k">break</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">uid</span> <span class="o">=</span> <span class="n">uid</span>
        <span class="n">session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">short_url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">url_for</span><span class="p">(</span><span class="s">&#39;link&#39;</span><span class="p">,</span> <span class="n">uid</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">uid</span><span class="p">,</span> <span class="n">_external</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&#39;&lt;URL </span><span class="si">%r</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">uid</span>

<span class="n">mapper</span><span class="p">(</span><span class="n">URL</span><span class="p">,</span> <span class="n">url_table</span><span class="p">)</span>
</pre></div>
</div>
<p>This module is pretty straightforward.  We import all the stuff we need from
SQLAlchemy and create a table.  Then we add a class for this table and we map
them both together.  For detailed explanations regarding SQLAlchemy you should
have a look at the <a class="reference external" href="http://www.sqlalchemy.org/docs/05/ormtutorial.html">excellent tutorial</a>.</p>
<p>In the constructor we generate a unique ID until we find an id which is still
free to use.
What&#8217;s missing is the <cite>get_random_uid</cite> function we have to add to the utils
module:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">sample</span><span class="p">,</span> <span class="n">randrange</span>

<span class="n">URL_CHARS</span> <span class="o">=</span> <span class="s">&#39;abcdefghijkmpqrstuvwxyzABCDEFGHIJKLMNPQRST23456789&#39;</span>

<span class="k">def</span> <span class="nf">get_random_uid</span><span class="p">():</span>
    <span class="k">return</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sample</span><span class="p">(</span><span class="n">URL_CHARS</span><span class="p">,</span> <span class="n">randrange</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">9</span><span class="p">)))</span>
</pre></div>
</div>
<p>Once that is done we can use <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">initdb</span></tt> to initialize the
database and play around with the stuff using <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">shell</span></tt>:</p>
<div class="highlight-pycon"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">shorty.models</span> <span class="kn">import</span> <span class="n">session</span><span class="p">,</span> <span class="n">URL</span>
</pre></div>
</div>
<p>Now we can add some URLs to the database:</p>
<div class="highlight-pycon"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">urls</span> <span class="o">=</span> <span class="p">[</span><span class="n">URL</span><span class="p">(</span><span class="s">&#39;http://example.org/&#39;</span><span class="p">),</span> <span class="n">URL</span><span class="p">(</span><span class="s">&#39;http://localhost:5000/&#39;</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[&lt;URL &#39;5cFbsk&#39;&gt;, &lt;URL &#39;mpugsT&#39;&gt;]</span>
</pre></div>
</div>
<p>As you can see we have to commit in order to send the urls to the database.
Let&#8217;s create a private item with a custom uid:</p>
<div class="highlight-pycon"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="p">(</span><span class="s">&#39;http://werkzeug.pocoo.org/&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="s">&#39;werkzeug-webpage&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
</div>
<p>And query them all:</p>
<div class="highlight-pycon"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">filter_by</span><span class="p">(</span><span class="n">public</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[&lt;URL &#39;werkzeug-webpage&#39;&gt;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">filter_by</span><span class="p">(</span><span class="n">public</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[&lt;URL &#39;5cFbsk&#39;&gt;, &lt;URL &#39;mpugsT&#39;&gt;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;werkzeug-webpage&#39;</span><span class="p">)</span>
<span class="go">&lt;URL &#39;werkzeug-webpage&#39;&gt;</span>
</pre></div>
</div>
<p>Now that we have some data in the database and we are somewhat familiar with
the way SQLAlchemy works, it&#8217;s time to create our views.</p>
</div>
<div class="section" id="part-4-the-view-functions">
<h2>Part 4: The View Functions<a class="headerlink" href="#part-4-the-view-functions" title="Permalink to this headline">¶</a></h2>
<p>Now after some playing with SQLAlchemy we can go back to Werkzeug and start
creating our view functions.  The term &#8220;view function&#8221; is derived from Django
which also calls the functions that render templates &#8220;view functions&#8221;.  So
our example is MTV (Model, View, Template) and not MVC (Model, View,
Controller).  They are probably the same but it&#8217;s a lot easier to use the
Django way of naming those things.</p>
<p>For the beginning we just create a view function for new URLs and a function
that displays a message about a new link.  All that code goes into our still
empty <tt class="docutils literal"><span class="pre">views.py</span></tt> file:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">redirect</span>
<span class="kn">from</span> <span class="nn">werkzeug.exceptions</span> <span class="kn">import</span> <span class="n">NotFound</span>
<span class="kn">from</span> <span class="nn">shorty.utils</span> <span class="kn">import</span> <span class="n">session</span><span class="p">,</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">expose</span><span class="p">,</span> <span class="n">validate_url</span><span class="p">,</span> \
     <span class="n">url_for</span>
<span class="kn">from</span> <span class="nn">shorty.models</span> <span class="kn">import</span> <span class="n">URL</span>

<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">new</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">error</span> <span class="o">=</span> <span class="n">url</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">&#39;POST&#39;</span><span class="p">:</span>
        <span class="n">url</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;url&#39;</span><span class="p">)</span>
        <span class="n">alias</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;alias&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">validate_url</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
            <span class="n">error</span> <span class="o">=</span> <span class="s">&quot;I&#39;m sorry but you cannot shorten this URL.&quot;</span>
        <span class="k">elif</span> <span class="n">alias</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">alias</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">140</span><span class="p">:</span>
                <span class="n">error</span> <span class="o">=</span> <span class="s">&#39;Your alias is too long&#39;</span>
            <span class="k">elif</span> <span class="s">&#39;/&#39;</span> <span class="ow">in</span> <span class="n">alias</span><span class="p">:</span>
                <span class="n">error</span> <span class="o">=</span> <span class="s">&#39;Your alias might not include a slash&#39;</span>
            <span class="k">elif</span> <span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">alias</span><span class="p">):</span>
                <span class="n">error</span> <span class="o">=</span> <span class="s">&#39;The alias you have requested exists already&#39;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">error</span><span class="p">:</span>
            <span class="n">uid</span> <span class="o">=</span> <span class="n">URL</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="s">&#39;private&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">,</span> <span class="n">alias</span><span class="p">)</span><span class="o">.</span><span class="n">uid</span>
            <span class="n">session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
            <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">url_for</span><span class="p">(</span><span class="s">&#39;display&#39;</span><span class="p">,</span> <span class="n">uid</span><span class="o">=</span><span class="n">uid</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&#39;new.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="n">error</span><span class="p">,</span> <span class="n">url</span><span class="o">=</span><span class="n">url</span><span class="p">)</span>

<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/display/&lt;uid&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">uid</span><span class="p">):</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">uid</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">url</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">NotFound</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&#39;display.html&#39;</span><span class="p">,</span> <span class="n">url</span><span class="o">=</span><span class="n">url</span><span class="p">)</span>

<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/u/&lt;uid&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">link</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">uid</span><span class="p">):</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">uid</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">url</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">NotFound</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">url</span><span class="o">.</span><span class="n">target</span><span class="p">,</span> <span class="mi">301</span><span class="p">)</span>

<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/list/&#39;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&#39;page&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/list/&lt;int:page&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">list</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">page</span><span class="p">):</span>
    <span class="k">pass</span>
</pre></div>
</div>
<p>Quite a lot of code again, but most of it is just plain old form validation.
Basically we specify two functions: <cite>new</cite> and <cite>display</cite> and
decorate them with our <cite>expose</cite> decorator from the utils.  This decorator
adds a new URL rule to the map by passing all parameters to the constructor
of a rule object and setting the endpoint to the name of the function.  So we
can easily build URLs to those functions by using their name as endpoint.</p>
<p>Keep in mind that this is not necessarily a good idea for bigger applications.
In such cases it&#8217;s encouraged to use the full import name with a common prefix
as endpoint or something similar.  Otherwise it becomes pretty confusing.</p>
<p>The form validation in the <cite>new</cite> method is pretty straightforward.  We check
if the current method is <cite>POST</cite>, if yes we get the data from the request and
validate it.  If there is no error we create a new <cite>URL</cite> object, commit it to
the database and redirect to the display page.</p>
<p>The <cite>display</cite> function is not much more complex.  The URL rule expects a
parameter called <cite>uid</cite>, which the function accepts.  Then we look up the URL
rule with the given uid and render a template by passing the URL object to it.</p>
<p>If the URL does not exist we raise a <a title="werkzeug.exceptions.NotFound" class="reference external" href="exceptions.html#werkzeug.exceptions.NotFound"><tt class="xref py py-exc docutils literal"><span class="pre">NotFound</span></tt></a> exception
which displays a generic &#8220;404 Page Not Found&#8221; page.  We can later replace it
by a custom error page by catching that exception before the generic
<a title="werkzeug.exceptions.HTTPException" class="reference external" href="exceptions.html#werkzeug.exceptions.HTTPException"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPException</span></tt></a> in our WSGI application.</p>
<p>The <cite>link</cite> view function is used by our models in the <cite>short_url</cite> property
and is the short URL we provide.  So if the URL uid is <tt class="docutils literal"><span class="pre">foobar</span></tt> the URL
will be available as <tt class="docutils literal"><span class="pre">http://localhost:5000/u/foobar</span></tt>.</p>
<p>The <cite>list</cite> view function has not yet been written, we will do that later.  But
what&#8217;s important is that this function takes a URL parameter which is
optional.  The first decorator tells Werkzeug that if just <tt class="docutils literal"><span class="pre">/page/</span></tt> is
requested it will assume that the page equals 1.  Even more important is the
fact that Werkzeug also normalizes the URLs.  So if you requested <tt class="docutils literal"><span class="pre">/page</span></tt> or
<tt class="docutils literal"><span class="pre">/page/1</span></tt>, you will be redirected to <tt class="docutils literal"><span class="pre">/page/</span></tt> in both cases.
This makes Google happy and comes for free.  If you don&#8217;t like that behavior,
you can also disable it.</p>
<p>And again we have imported two objects from the utils module that
don&#8217;t exist yet.  One of those should render a jinja template into a response
object, the other one validates a URL.  So let&#8217;s add those to <tt class="docutils literal"><span class="pre">utils.py</span></tt>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span>
<span class="kn">from</span> <span class="nn">urlparse</span> <span class="kn">import</span> <span class="n">urlparse</span>
<span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">jinja2</span> <span class="kn">import</span> <span class="n">Environment</span><span class="p">,</span> <span class="n">FileSystemLoader</span>

<span class="n">ALLOWED_SCHEMES</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><span class="s">&#39;http&#39;</span><span class="p">,</span> <span class="s">&#39;https&#39;</span><span class="p">,</span> <span class="s">&#39;ftp&#39;</span><span class="p">,</span> <span class="s">&#39;ftps&#39;</span><span class="p">])</span>
<span class="n">TEMPLATE_PATH</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span> <span class="s">&#39;templates&#39;</span><span class="p">)</span>
<span class="n">jinja_env</span> <span class="o">=</span> <span class="n">Environment</span><span class="p">(</span><span class="n">loader</span><span class="o">=</span><span class="n">FileSystemLoader</span><span class="p">(</span><span class="n">TEMPLATE_PATH</span><span class="p">))</span>
<span class="n">jinja_env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s">&#39;url_for&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">url_for</span>

<span class="k">def</span> <span class="nf">render_template</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="o">**</span><span class="n">context</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="n">jinja_env</span><span class="o">.</span><span class="n">get_template</span><span class="p">(</span><span class="n">template</span><span class="p">)</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="o">**</span><span class="n">context</span><span class="p">),</span>
                    <span class="n">mimetype</span><span class="o">=</span><span class="s">&#39;text/html&#39;</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">validate_url</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">urlparse</span><span class="p">(</span><span class="n">url</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">ALLOWED_SCHEMES</span>
</pre></div>
</div>
<p>That&#8217;s it, basically.  The validation function checks if our URL looks like an
HTTP or FTP URL.  We do this whitelisting to ensure nobody submits any
dangerous JavaScript or similar URLs.  The <cite>render_template</cite> function is not
much more complicated either, it basically looks up a template on the file
system in the <cite>templates</cite> folder and renders it as response.</p>
<p>Another thing we do here is passing the <cite>url_for</cite> function into the global
template context so that we can build URLs in the templates too.</p>
<p>Now that we have our first two view functions it&#8217;s time to add the templates.</p>
</div>
<div class="section" id="part-5-the-templates">
<h2>Part 5: The Templates<a class="headerlink" href="#part-5-the-templates" title="Permalink to this headline">¶</a></h2>
<p>We have decided to use Jinja templates in this example.  If you are used to
Django templates you should feel at home, if you have worked with PHP so far
you can compare the Jinja templates with smarty.  If you have used PHP as
templating language until now you should have a look at <a class="reference external" href="http://www.makotemplates.org/">Mako</a> for your next
project.</p>
<p><strong>Security Warning</strong>: We are using Jinja here which is a text based template
engine.  As a matter of fact, Jinja has no idea what it is dealing with, so
if you want to create HTML template it&#8217;s your responsibility to escape <em>all</em>
values that might include, at some point, any of the following characters: <tt class="docutils literal"><span class="pre">&gt;</span></tt>,
<tt class="docutils literal"><span class="pre">&lt;</span></tt>, <tt class="docutils literal"><span class="pre">&amp;</span></tt>, and <tt class="docutils literal"><span class="pre">&quot;</span></tt>.  As you can see from the examples below we don&#8217;t
escape URLs.  The reason is that we won&#8217;t have any ampersands in the URL and
as such it&#8217;s safe to omit it.</p>
<p>For simplicity we will use HTML 4 in our templates.  If you have already
some experience with XHTML you can adopt the templates to XHTML.  But keep
in mind that the example stylesheet from below does not work with XHTML.</p>
<p>One of the cool things Jinja inherited from Django is template inheritance.
Template inheritance means that we can put often used elements into a base
template and fill in placeholders.  For example all the doctype and HTML base
frame goes into a file called <tt class="docutils literal"><span class="pre">templates/layout.html</span></tt>:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;</span>
<span class="cp"> &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;</span>
<span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;</span>
  <span class="nt">&lt;title&gt;</span>Shorty<span class="nt">&lt;/title&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
  <span class="nt">&lt;h1&gt;&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;new&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>Shorty<span class="nt">&lt;/a&gt;&lt;/h1&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;body&quot;</span><span class="nt">&gt;</span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;footer&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;new&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>new<span class="nt">&lt;/a&gt;</span> |
    <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;list&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>list<span class="nt">&lt;/a&gt;</span> |
    use shorty for good, not for evil
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</pre></div>
</div>
<p>And we can inherit from this base template in our <tt class="docutils literal"><span class="pre">templates/new.html</span></tt>:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s1">&#39;layout.html&#39;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
  <span class="nt">&lt;h2&gt;</span>Create a Shorty-URL!<span class="nt">&lt;/h2&gt;</span>
  <span class="cp">{%</span> <span class="k">if</span> <span class="nv">error</span> <span class="cp">%}</span><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;error&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">error</span> <span class="cp">}}</span><span class="nt">&lt;/div&gt;</span><span class="cp">{%</span> <span class="k">endif</span> -<span class="cp">%}</span>
  <span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">&quot;&quot;</span> <span class="na">method=</span><span class="s">&quot;post&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;p&gt;</span>Enter the URL you want to shorten<span class="nt">&lt;/p&gt;</span>
    <span class="nt">&lt;p&gt;&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">name=</span><span class="s">&quot;url&quot;</span> <span class="na">id=</span><span class="s">&quot;url&quot;</span> <span class="na">value=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url</span><span class="o">|</span><span class="nf">e</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;&lt;/p&gt;</span>
    <span class="nt">&lt;p&gt;</span>Optionally you can give the URL a memorable name<span class="nt">&lt;/p&gt;</span>
    <span class="nt">&lt;p&gt;&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">id=</span><span class="s">&quot;alias&quot;</span> <span class="na">name=</span><span class="s">&quot;alias&quot;</span><span class="nt">&gt;</span><span class="c">{#</span>
<span class="c">     #}</span><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;submit&quot;</span> <span class="na">id=</span><span class="s">&quot;submit&quot;</span> <span class="na">value=</span><span class="s">&quot;Do!&quot;</span><span class="nt">&gt;&lt;/p&gt;</span>
    <span class="nt">&lt;p&gt;&lt;input</span> <span class="na">type=</span><span class="s">&quot;checkbox&quot;</span> <span class="na">name=</span><span class="s">&quot;private&quot;</span> <span class="na">id=</span><span class="s">&quot;private&quot;</span><span class="nt">&gt;</span>
       <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;private&quot;</span><span class="nt">&gt;</span>make this URL private, so don&#39;t list it<span class="nt">&lt;/label&gt;&lt;/p&gt;</span>
  <span class="nt">&lt;/form&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>If you&#8217;re wondering about the comment between the two input elements, this is
a neat trick to keep the templates clean but not create whitespace between
those two.  We&#8217;ve prepared a stylesheet you can use which depends on not having
a whitespace there.</p>
<p>And then a second template for the display page (<tt class="docutils literal"><span class="pre">templates/display.html</span></tt>):</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s1">&#39;layout.html&#39;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
  <span class="nt">&lt;h2&gt;</span>Shortened URL<span class="nt">&lt;/h2&gt;</span>
  <span class="nt">&lt;p&gt;</span>
    The URL <span class="cp">{{</span> <span class="nv">url.target</span><span class="o">|</span><span class="nf">urlize</span><span class="o">(</span><span class="m">40</span><span class="o">,</span> <span class="kp">true</span><span class="o">)</span> <span class="cp">}}</span>
    was shortened to <span class="cp">{{</span> <span class="nv">url.short_url</span><span class="o">|</span><span class="nf">urlize</span> <span class="cp">}}</span>.
  <span class="nt">&lt;/p&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>The <cite>urlize</cite> filter is provided by Jinja and translates a URL(s) in a
text into clickable links.  If you pass it an integer it will shorten the
captions of those links to that number of characters, passing it true as
second parameter adds a <cite>nofollow</cite> flag.</p>
<p>Now that we have our first two templates it&#8217;s time to fire up the server and
look at those part of the application that work already: adding new URLs and
getting redirected.</p>
</div>
<div class="section" id="intermission-adding-the-design">
<h2>Intermission: Adding The Design<a class="headerlink" href="#intermission-adding-the-design" title="Permalink to this headline">¶</a></h2>
<p>Now it&#8217;s time to do something different: adding a design.  Design elements are
usually in static CSS stylesheets so we have to put some static files
somewhere.  But that&#8217;s a little big tricky.  If you have worked with PHP so
far you have probably noticed that there is no such thing as translating the
URL to filesystem paths and accessing static files right from the URL.  You
have to explicitly tell the webserver or our development server that some
path holds static files.</p>
<p>Django even recommends a separate subdomain and standalone server for the
static files which is a terribly good idea for heavily loaded environments but
somewhat of an overkill for this simple application.</p>
<p>So here is the deal: We let our application host the static files, but in
production mode you should probably tell the apache to serve those files by
using an <cite>Alias</cite> directive in the apache config:</p>
<div class="highlight-apache"><div class="highlight"><pre><span class="nb">Alias</span> <span class="sx">/static</span> <span class="sx">/path/to/static/files</span>
</pre></div>
</div>
<p>This will be a lot faster.</p>
<p>But how do we tell our application that we want it to share the static folder
from our application package as <tt class="docutils literal"><span class="pre">/static</span></tt>?.  Fortunately that&#8217;s pretty
simple because Werkzeug provides a WSGI middleware for that.  Now there are
two ways to hook that middleware in.  One way is to wrap the whole application
in that middleware (we really don&#8217;t recommend this one) and the other is to
just wrap the dispatching function (much better because we don&#8217;t lose the
reference to the application object).  So head back to <tt class="docutils literal"><span class="pre">application.py</span></tt>
and do some code refactoring there.</p>
<p>First of all you have to add a new import and calculate the path to the
static files:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span>
<span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">SharedDataMiddleware</span>

<span class="n">STATIC_PATH</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span> <span class="s">&#39;static&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>It may be better to put the path calculation into the <tt class="docutils literal"><span class="pre">utils.py</span></tt> file
because we already calculate the path to the templates there.  But it doesn&#8217;t
really matter and for simplicity we can leave it in the application module.</p>
<p>So how do we wrap our dispatching function?  In theory we just have to say
<tt class="docutils literal"><span class="pre">self.__call__</span> <span class="pre">=</span> <span class="pre">wrap(self.__call__)</span></tt> but unfortunately that doesn&#8217;t work in
python.  But it&#8217;s not much harder.  Just rename <cite>__call__</cite> to <cite>dispatch</cite> and
add a new <cite>__call__</cite> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
</pre></div>
</div>
<p>Now we can go into our <cite>__init__</cite> function and hook in the middleware by
wrapping the <cite>dispatch</cite> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="bp">self</span><span class="o">.</span><span class="n">dispatch</span> <span class="o">=</span> <span class="n">SharedDataMiddleware</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dispatch</span><span class="p">,</span> <span class="p">{</span>
    <span class="s">&#39;/static&#39;</span><span class="p">:</span>  <span class="n">STATIC_PATH</span>
<span class="p">})</span>
</pre></div>
</div>
<p>Now that wasn&#8217;t that hard.  This way you can now hook in WSGI middlewares
inside the application class!</p>
<p>Another good idea now is to tell our <cite>url_map</cite> in the utils module the
location of our static files by adding a rule.  This way we can generate URLs
to the static files in the templates:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">url_map</span> <span class="o">=</span> <span class="n">Map</span><span class="p">([</span><span class="n">Rule</span><span class="p">(</span><span class="s">&#39;/static/&lt;file&gt;&#39;</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="s">&#39;static&#39;</span><span class="p">,</span> <span class="n">build_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)])</span>
</pre></div>
</div>
<p>Now we can open our <tt class="docutils literal"><span class="pre">templates/layout.html</span></tt> file again and add a link to the
stylesheet <tt class="docutils literal"><span class="pre">style.css</span></tt>, which we are going to create afterwards:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">type=</span><span class="s">&quot;text/css&quot;</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;static&#39;</span><span class="o">,</span> <span class="nv">file</span><span class="o">=</span><span class="s1">&#39;style.css&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>
</pre></div>
</div>
<p>This of course goes into the <cite>&lt;head&gt;</cite> tag where currently just the title is.</p>
<p>You can now design a nice layout for it or use the <a class="reference external" href="http://dev.pocoo.org/projects/werkzeug/browser/examples/shorty/static/style.css">example stylesheet</a> if
you want.  In both cases the file you have to create is called
<tt class="docutils literal"><span class="pre">static/style.css</span></tt></p>
</div>
<div class="section" id="part-6-listing-public-urls">
<h2>Part 6: Listing Public URLs<a class="headerlink" href="#part-6-listing-public-urls" title="Permalink to this headline">¶</a></h2>
<p>Now we want to list all of the public URLs on the list page.  That shouldn&#8217;t
be a big problem but we will have to do some sort of pagination.  Because if
we print all URLs at once we have sooner or later an endless page that takes
minutes to load.</p>
<p>So let&#8217;s start by adding a <cite>Pagination</cite> class into our utils module:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">cached_property</span>

<span class="k">class</span> <span class="nc">Pagination</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">,</span> <span class="n">per_page</span><span class="p">,</span> <span class="n">page</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">per_page</span> <span class="o">=</span> <span class="n">per_page</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">page</span> <span class="o">=</span> <span class="n">page</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>

    <span class="nd">@cached_property</span>
    <span class="k">def</span> <span class="nf">count</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">count</span><span class="p">()</span>

    <span class="nd">@cached_property</span>
    <span class="k">def</span> <span class="nf">entries</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">offset</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">page</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">per_page</span><span class="p">)</span> \
                         <span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">per_page</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>

    <span class="n">has_previous</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">page</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">has_next</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">page</span> <span class="o">&lt;</span> <span class="n">x</span><span class="o">.</span><span class="n">pages</span><span class="p">)</span>
    <span class="n">previous</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">url_for</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">page</span><span class="o">=</span><span class="n">x</span><span class="o">.</span><span class="n">page</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
    <span class="nb">next</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">url_for</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">page</span><span class="o">=</span><span class="n">x</span><span class="o">.</span><span class="n">page</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">pages</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">x</span><span class="o">.</span><span class="n">count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="n">x</span><span class="o">.</span><span class="n">per_page</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
<p>This is a very simple class that does most of the pagination for us.  We
can pass at an unexecuted SQLAlchemy query, the number of items per page,
the current page and the endpoint, which will be used for URL generation.
The <a title="werkzeug.cached_property" class="reference external" href="utils.html#werkzeug.cached_property"><tt class="xref py py-func docutils literal"><span class="pre">cached_property()</span></tt></a> decorator you see works pretty much like the
normal <a title="(in Python v2.7)" class="reference external" href="http://docs.python.org/dev/library/functions.html#property"><tt class="xref py py-func docutils literal"><span class="pre">property()</span></tt></a> decorator, just that it memorizes the result.  We
won&#8217;t cover that class in detail but basically the idea is that accessing
<cite>pagination.entries</cite> returns the items for the current page and that the
other properties return meaningful values so that we can use them in the
template.</p>
<p>Now we can import the <cite>Pagination</cite> class into our views module and add some
code to the <cite>list</cite> function:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">shorty.utils</span> <span class="kn">import</span> <span class="n">Pagination</span>

<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/list/&#39;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&#39;page&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="nd">@expose</span><span class="p">(</span><span class="s">&#39;/list/&lt;int:page&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">list</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">page</span><span class="p">):</span>
    <span class="n">query</span> <span class="o">=</span> <span class="n">URL</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">filter_by</span><span class="p">(</span><span class="n">public</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">pagination</span> <span class="o">=</span> <span class="n">Pagination</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="n">page</span><span class="p">,</span> <span class="s">&#39;list&#39;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">pagination</span><span class="o">.</span><span class="n">page</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">pagination</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">NotFound</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&#39;list.html&#39;</span><span class="p">,</span> <span class="n">pagination</span><span class="o">=</span><span class="n">pagination</span><span class="p">)</span>
</pre></div>
</div>
<p>The if condition in this function basically ensures that status code 404 is
returned if we are not on the first page and there aren&#8217;t any entries to display
(Accessing something like <tt class="docutils literal"><span class="pre">/list/42</span></tt> without entries on that page and not
returning a 404 status code would be considered bad style.)</p>
<p>And finally the template (<tt class="docutils literal"><span class="pre">templates/list.html</span></tt>):</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s1">&#39;layout.html&#39;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
  <span class="nt">&lt;h2&gt;</span>List of URLs<span class="nt">&lt;/h2&gt;</span>
  <span class="nt">&lt;ul&gt;</span>
  <span class="cp">{%</span>- <span class="k">for</span> <span class="nv">url</span> <span class="k">in</span> <span class="nv">pagination.entries</span> <span class="cp">%}</span>
    <span class="nt">&lt;li&gt;&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url.short_url</span><span class="o">|</span><span class="nf">e</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">url.uid</span><span class="o">|</span><span class="nf">e</span> <span class="cp">}}</span><span class="nt">&lt;/a&gt;</span> <span class="ni">&amp;raquo;</span>
        <span class="nt">&lt;small&gt;</span><span class="cp">{{</span> <span class="nv">url.target</span><span class="o">|</span><span class="nf">urlize</span><span class="o">(</span><span class="m">38</span><span class="o">,</span> <span class="kp">true</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/small&gt;&lt;/li&gt;</span>
  <span class="cp">{%</span>- <span class="k">else</span> <span class="cp">%}</span>
    <span class="nt">&lt;li&gt;&lt;em&gt;</span>no URls shortened yet<span class="nt">&lt;/em&gt;&lt;/li&gt;</span>
  <span class="cp">{%</span>- <span class="k">endfor</span> <span class="cp">%}</span>
  <span class="nt">&lt;/ul&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;pagination&quot;</span><span class="nt">&gt;</span>
    <span class="cp">{%</span>- <span class="k">if</span> <span class="nv">pagination.has_previous</span> <span class="cp">%}</span><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">pagination.previous</span>
        <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span><span class="ni">&amp;laquo;</span> Previous<span class="nt">&lt;/a&gt;</span>
    <span class="cp">{%</span>- <span class="k">else</span> <span class="cp">%}</span><span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;inactive&quot;</span><span class="nt">&gt;</span><span class="ni">&amp;laquo;</span> Previous<span class="nt">&lt;/span&gt;</span><span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
    | <span class="cp">{{</span> <span class="nv">pagination.page</span> <span class="cp">}}</span> |
    <span class="cp">{%</span> <span class="k">if</span> <span class="nv">pagination.has_next</span> <span class="cp">%}</span><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">pagination.next</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>Next <span class="ni">&amp;raquo;</span><span class="nt">&lt;/a&gt;</span>
    <span class="cp">{%</span>- <span class="k">else</span> <span class="cp">%}</span><span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;inactive&quot;</span><span class="nt">&gt;</span>Next <span class="ni">&amp;raquo;</span><span class="nt">&lt;/span&gt;</span><span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
</div>
<div class="section" id="the-end-result">
<h2>The End Result<a class="headerlink" href="#the-end-result" title="Permalink to this headline">¶</a></h2>
<p>And this is what it looks like in the end, with the example stylesheet
from above:</p>
<div align="center" class="align-center"><img alt="a screenshot of the final shorty application" class="align-center" src="_images/shorty-screenshot.png" /></div>
</div>
<div class="section" id="bonus-styling-404-error-pages">
<h2>Bonus: Styling 404 Error Pages<a class="headerlink" href="#bonus-styling-404-error-pages" title="Permalink to this headline">¶</a></h2>
<p>Now that we&#8217;ve finished our application we can do some small improvements such
as custom 404 error pages.  That&#8217;s pretty simple.  The first thing we have to
do is creating a new function called <cite>not_found</cite> in the view that renders a
template:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">not_found</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&#39;not_found.html&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Then we have to go into our application module and import the
<a title="werkzeug.exceptions.NotFound" class="reference external" href="exceptions.html#werkzeug.exceptions.NotFound"><tt class="xref py py-exc docutils literal"><span class="pre">NotFound</span></tt></a> exception:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">werkzeug.exceptions</span> <span class="kn">import</span> <span class="n">NotFound</span>
</pre></div>
</div>
<p>Finally we have to catch it and translate it into a response.  This except
block goes right <strong>before</strong> the except block of the
<a title="werkzeug.exceptions.HTTPException" class="reference external" href="exceptions.html#werkzeug.exceptions.HTTPException"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPException</span></tt></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">try</span><span class="p">:</span>
    <span class="o">...</span> <span class="c"># this stays the same</span>
<span class="k">except</span> <span class="n">NotFound</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
    <span class="n">response</span> <span class="o">=</span> <span class="n">views</span><span class="o">.</span><span class="n">not_found</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
    <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">404</span>
<span class="k">except</span> <span class="n">HTTPException</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
    <span class="o">...</span> <span class="c"># this stays the same</span>
</pre></div>
</div>
<p>Now add a template <tt class="docutils literal"><span class="pre">templates/not_found.html</span></tt> and you&#8217;re done:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s1">&#39;layout.html&#39;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
  <span class="nt">&lt;h2&gt;</span>Page Not Found<span class="nt">&lt;/h2&gt;</span>
  <span class="nt">&lt;p&gt;</span>
    The page you have requested does not exist on this server.  What about
    <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;new&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>adding a new URL<span class="nt">&lt;/a&gt;</span>?
  <span class="nt">&lt;/p&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
</div>
<div class="section" id="outro">
<h2>Outro<a class="headerlink" href="#outro" title="Permalink to this headline">¶</a></h2>
<p>This tutorial covers everything you need to get started with Werkzeug,
SQLAlchemy and Jinja and should help you find the best solution for your
application.  For some more complex examples that also use different setups
and ideas for dispatching have a look at the <a class="reference external" href="http://dev.pocoo.org/projects/werkzeug/browser/examples">examples folder</a>.</p>
<p>Have fun with Werkzeug!</p>
</div>
</div>


        <div style="clear: both"></div>
      </div>
      <div class="footer">
        © Copyright 2008 by the <a href="http://pocoo.org/">Pocoo Team</a>,
        documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
      </div>
    </div>
  </body>
</html>