This file is indexed.

/usr/share/doc/python-pecan-doc/html/databases.html is in python-pecan-doc 1.2.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Working with Databases, Transactions, and ORM’s &#8212; Pecan 1.2.1 documentation</title>
    <link rel="stylesheet" href="_static/nature.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '1.2.1',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true,
        SOURCELINK_SUFFIX: '.txt'
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Custom Error Documents" href="errors.html" />
    <link rel="prev" title="Working with Sessions and User Authentication" href="sessions.html" /> 
  </head>
  <body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="errors.html" title="Custom Error Documents"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="sessions.html" title="Working with Sessions and User Authentication"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="index.html">Pecan 1.2.1 documentation</a> &#187;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="working-with-databases-transactions-and-orm-s">
<span id="databases"></span><h1>Working with Databases, Transactions, and ORM’s<a class="headerlink" href="#working-with-databases-transactions-and-orm-s" title="Permalink to this headline"></a></h1>
<p>Pecan provides no opinionated support for working with databases, but
it’s easy to hook into your ORM of choice.  This article details best
practices for integrating the popular Python ORM, <a class="reference external" href="http://sqlalchemy.org">SQLAlchemy</a>, into
your Pecan project.</p>
<div class="section" id="init-model-and-preparing-your-model">
<span id="init-model"></span><h2><code class="docutils literal"><span class="pre">init_model</span></code> and Preparing Your Model<a class="headerlink" href="#init-model-and-preparing-your-model" title="Permalink to this headline"></a></h2>
<p>Pecan’s default quickstart project includes an empty stub directory
for implementing your model as you see fit.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span>.
└── test_project
    ├── app.py
    ├── __init__.py
    ├── controllers
    ├── model
    │   ├── __init__.py
    └── templates
</pre></div>
</div>
<p>By default, this module contains a special method, <code class="xref py py-func docutils literal"><span class="pre">init_model()</span></code>.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pecan</span> <span class="k">import</span> <span class="n">conf</span>

<span class="k">def</span> <span class="nf">init_model</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This is a stub method which is called at application startup time.</span>

<span class="sd">    If you need to bind to a parsed database configuration, set up tables</span>
<span class="sd">    or ORM classes, or perform any database initialization, this is the</span>
<span class="sd">    recommended place to do it.</span>

<span class="sd">    For more information working with databases, and some common recipes,</span>
<span class="sd">    see https://pecan.readthedocs.io/en/latest/databases.html</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">pass</span>
</pre></div>
</div>
<p>The purpose of this method is to determine bindings from your
configuration file and create necessary engines, pools,
etc. according to your ORM or database toolkit of choice.</p>
<p>Additionally, your project’s <code class="xref py py-mod docutils literal"><span class="pre">model</span></code> module can be used to define
functions for common binding operations, such as starting
transactions, committing or rolling back work, and clearing a session.
This is also the location in your project where object and relation
definitions should be defined.  Here’s what a sample Pecan
configuration file with database bindings might look like.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># Server Specific Configurations</span>
<span class="n">server</span> <span class="o">=</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>

<span class="c1"># Pecan Application Configurations</span>
<span class="n">app</span> <span class="o">=</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>

<span class="c1"># Bindings and options to pass to SQLAlchemy&#39;s ``create_engine``</span>
<span class="n">sqlalchemy</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s1">&#39;url&#39;</span>           <span class="p">:</span> <span class="s1">&#39;mysql://root:@localhost/dbname?charset=utf8&amp;use_unicode=0&#39;</span><span class="p">,</span>
    <span class="s1">&#39;echo&#39;</span>          <span class="p">:</span> <span class="kc">False</span><span class="p">,</span>
    <span class="s1">&#39;echo_pool&#39;</span>     <span class="p">:</span> <span class="kc">False</span><span class="p">,</span>
    <span class="s1">&#39;pool_recycle&#39;</span>  <span class="p">:</span> <span class="mi">3600</span><span class="p">,</span>
    <span class="s1">&#39;encoding&#39;</span>      <span class="p">:</span> <span class="s1">&#39;utf-8&#39;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>And a basic model implementation that can be used to configure and
bind using SQLAlchemy.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pecan</span>                  <span class="k">import</span> <span class="n">conf</span>
<span class="kn">from</span> <span class="nn">sqlalchemy</span>             <span class="k">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span>         <span class="k">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span>

<span class="n">Session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</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="k">def</span> <span class="nf">_engine_from_config</span><span class="p">(</span><span class="n">configuration</span><span class="p">):</span>
    <span class="n">configuration</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">configuration</span><span class="p">)</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">configuration</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;url&#39;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">create_engine</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="o">**</span><span class="n">configuration</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">init_model</span><span class="p">():</span>
    <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">_engine_from_config</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">start</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy</span><span class="o">.</span><span class="n">engine</span>
    <span class="n">metadata</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">Session</span><span class="o">.</span><span class="n">bind</span>

<span class="k">def</span> <span class="nf">commit</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">rollback</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">clear</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="binding-within-the-application">
<h2>Binding Within the Application<a class="headerlink" href="#binding-within-the-application" title="Permalink to this headline"></a></h2>
<p>There are several approaches to wrapping your application’s requests
with calls to appropriate model function calls.  One approach is WSGI
middleware.  We also recommend Pecan <a class="reference internal" href="hooks.html#hooks"><span class="std std-ref">Pecan Hooks</span></a>.  Pecan comes with
<a class="reference internal" href="pecan_hooks.html#pecan.hooks.TransactionHook" title="pecan.hooks.TransactionHook"><code class="xref py py-class docutils literal"><span class="pre">TransactionHook</span></code></a>, a hook which can be used to wrap
requests in database transactions for you.  To use it, simply include it in
your project’s <code class="docutils literal"><span class="pre">app.py</span></code> file and pass it a set of functions related to
database binding.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pecan</span> <span class="k">import</span> <span class="n">conf</span><span class="p">,</span> <span class="n">make_app</span>
<span class="kn">from</span> <span class="nn">pecan.hooks</span> <span class="k">import</span> <span class="n">TransactionHook</span>
<span class="kn">from</span> <span class="nn">test_project</span> <span class="k">import</span> <span class="n">model</span>

<span class="n">app</span> <span class="o">=</span> <span class="n">make_app</span><span class="p">(</span>
    <span class="n">conf</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">root</span><span class="p">,</span>
    <span class="n">static_root</span>     <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">static_root</span><span class="p">,</span>
    <span class="n">template_path</span>   <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">template_path</span><span class="p">,</span>
    <span class="n">debug</span>           <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">debug</span><span class="p">,</span>
    <span class="n">hooks</span>           <span class="o">=</span> <span class="p">[</span>
        <span class="n">TransactionHook</span><span class="p">(</span>
            <span class="n">model</span><span class="o">.</span><span class="n">start</span><span class="p">,</span>
            <span class="n">model</span><span class="o">.</span><span class="n">start_read_only</span><span class="p">,</span>
            <span class="n">model</span><span class="o">.</span><span class="n">commit</span><span class="p">,</span>
            <span class="n">model</span><span class="o">.</span><span class="n">rollback</span><span class="p">,</span>
            <span class="n">model</span><span class="o">.</span><span class="n">clear</span>
        <span class="p">)</span>
    <span class="p">]</span>
<span class="p">)</span>
</pre></div>
</div>
<p>In the above example, on HTTP <code class="docutils literal"><span class="pre">POST</span></code>, <code class="docutils literal"><span class="pre">PUT</span></code>, and <code class="docutils literal"><span class="pre">DELETE</span></code>
requests, <a class="reference internal" href="pecan_hooks.html#pecan.hooks.TransactionHook" title="pecan.hooks.TransactionHook"><code class="xref py py-class docutils literal"><span class="pre">TransactionHook</span></code></a> takes care of the transaction
automatically by following these rules:</p>
<ol class="arabic simple">
<li>Before controller routing has been determined, <code class="xref py py-func docutils literal"><span class="pre">model.start()</span></code>
is called.  This function should bind to the appropriate
SQLAlchemy engine and start a transaction.</li>
<li>Controller code is run and returns.</li>
<li>If your controller or template rendering fails and raises an
exception, <code class="xref py py-func docutils literal"><span class="pre">model.rollback()</span></code> is called and the original
exception is re-raised.  This allows you to rollback your database
transaction to avoid committing work when exceptions occur in your
application code.</li>
<li>If the controller returns successfully, <code class="xref py py-func docutils literal"><span class="pre">model.commit()</span></code> and
<code class="xref py py-func docutils literal"><span class="pre">model.clear()</span></code> are called.</li>
</ol>
<p>On idempotent operations (like HTTP <code class="docutils literal"><span class="pre">GET</span></code> and <code class="docutils literal"><span class="pre">HEAD</span></code> requests),
<a class="reference internal" href="pecan_hooks.html#pecan.hooks.TransactionHook" title="pecan.hooks.TransactionHook"><code class="xref py py-class docutils literal"><span class="pre">TransactionHook</span></code></a> handles transactions following different
rules.</p>
<ol class="arabic simple">
<li><code class="docutils literal"><span class="pre">model.start_read_only()</span></code> is called.  This function should bind
to your SQLAlchemy engine.</li>
<li>Controller code is run and returns.</li>
<li>If the controller returns successfully, <code class="docutils literal"><span class="pre">model.clear()</span></code> is
called.</li>
</ol>
<p>Also note that there is a useful <a class="reference internal" href="pecan_decorators.html#pecan.decorators.after_commit" title="pecan.decorators.after_commit"><code class="xref py py-func docutils literal"><span class="pre">after_commit()</span></code></a>
decorator provided in <a class="reference internal" href="pecan_decorators.html#pecan-decorators"><span class="std std-ref">pecan.decorators – Pecan Decorators</span></a>.</p>
</div>
<div class="section" id="splitting-reads-and-writes">
<h2>Splitting Reads and Writes<a class="headerlink" href="#splitting-reads-and-writes" title="Permalink to this headline"></a></h2>
<p>Employing the strategy above with <a class="reference internal" href="pecan_hooks.html#pecan.hooks.TransactionHook" title="pecan.hooks.TransactionHook"><code class="xref py py-class docutils literal"><span class="pre">TransactionHook</span></code></a> makes
it very simple to split database reads and writes based upon HTTP methods
(i.e., GET/HEAD requests are read-only and would potentially be routed
to a read-only database slave, while POST/PUT/DELETE requests require
writing, and would always bind to a master database with read/write
privileges).  It’s also possible to extend
<a class="reference internal" href="pecan_hooks.html#pecan.hooks.TransactionHook" title="pecan.hooks.TransactionHook"><code class="xref py py-class docutils literal"><span class="pre">TransactionHook</span></code></a> or write your own hook implementation for
more refined control over where and when database bindings are called.</p>
<p>Assuming a master/standby setup, where the master accepts write requests and
the standby can only get read requests, a Pecan configuration for sqlalchemy
could be:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># Server Specific Configurations</span>
<span class="n">server</span> <span class="o">=</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>

<span class="c1"># Pecan Application Configurations</span>
<span class="n">app</span> <span class="o">=</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>

<span class="c1"># Master database</span>
<span class="n">sqlalchemy_w</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s1">&#39;url&#39;</span><span class="p">:</span> <span class="s1">&#39;postgresql+psycopg2://root:@master_host/dbname&#39;</span><span class="p">,</span>
    <span class="s1">&#39;pool_recycle&#39;</span><span class="p">:</span> <span class="mi">3600</span><span class="p">,</span>
    <span class="s1">&#39;encoding&#39;</span><span class="p">:</span> <span class="s1">&#39;utf-8&#39;</span>
<span class="p">}</span>

<span class="c1"># Read Only database</span>
<span class="n">sqlalchemy_ro</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s1">&#39;url&#39;</span><span class="p">:</span> <span class="s1">&#39;postgresql+psycopg2://root:@standby_host/dbname&#39;</span><span class="p">,</span>
    <span class="s1">&#39;pool_recycle&#39;</span><span class="p">:</span> <span class="mi">3600</span><span class="p">,</span>
    <span class="s1">&#39;encoding&#39;</span><span class="p">:</span> <span class="s1">&#39;utf-8&#39;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Given the unique configuration settings for each database, the bindings would
need to change from what Pecan’s default quickstart provides (see
<a class="reference internal" href="#init-model"><span class="std std-ref">init_model and Preparing Your Model</span></a> section) to accommodate for both write and read only
requests:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pecan</span> <span class="k">import</span> <span class="n">conf</span>
<span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="k">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="k">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span>

<span class="n">Session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</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="k">def</span> <span class="nf">init_model</span><span class="p">():</span>
    <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_w</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">_engine_from_config</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_w</span><span class="p">)</span>
    <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_ro</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">_engine_from_config</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_ro</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">_engine_from_config</span><span class="p">(</span><span class="n">configuration</span><span class="p">):</span>
    <span class="n">configuration</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">configuration</span><span class="p">)</span>
    <span class="n">url</span> <span class="o">=</span> <span class="n">configuration</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;url&#39;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">create_engine</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="o">**</span><span class="n">configuration</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">start</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_w</span><span class="o">.</span><span class="n">engine</span>
    <span class="n">metadata</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_w</span><span class="o">.</span><span class="n">engine</span>


<span class="k">def</span> <span class="nf">start_read_only</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_ro</span><span class="o">.</span><span class="n">engine</span>
    <span class="n">metadata</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sqlalchemy_ro</span><span class="o">.</span><span class="n">engine</span>


<span class="k">def</span> <span class="nf">commit</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">rollback</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">clear</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">flush</span><span class="p">():</span>
    <span class="n">Session</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Working with Databases, Transactions, and ORM’s</a><ul>
<li><a class="reference internal" href="#init-model-and-preparing-your-model"><code class="docutils literal"><span class="pre">init_model</span></code> and Preparing Your Model</a></li>
<li><a class="reference internal" href="#binding-within-the-application">Binding Within the Application</a></li>
<li><a class="reference internal" href="#splitting-reads-and-writes">Splitting Reads and Writes</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="sessions.html"
                        title="previous chapter">Working with Sessions and User Authentication</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="errors.html"
                        title="next chapter">Custom Error Documents</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="_sources/databases.rst.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <div><input type="text" name="q" /></div>
      <div><input type="submit" value="Go" /></div>
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="errors.html" title="Custom Error Documents"
             >next</a> |</li>
        <li class="right" >
          <a href="sessions.html" title="Working with Sessions and User Authentication"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="index.html">Pecan 1.2.1 documentation</a> &#187;</li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2018, Jonathan LaCour.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.6.6.
    </div>
  </body>
</html>