LuisCastilloH
2018-05-16 fa9291399199c2f9d80d532a0e8c3dd50d8563fb
commit | author | age
da42d5 1
49d634 2 .. _quick_tour:
PE 3
ae9014 4 =====================
PE 5 Quick Tour of Pyramid
6 =====================
5b47ba 7
9b7f4d 8 Pyramid lets you start small and finish big.  This *Quick Tour* of Pyramid is
257ac0 9 for those who want to evaluate Pyramid, whether you are new to Python web
SP 10 frameworks, or a pro in a hurry. For more detailed treatment of each topic,
11 give the :ref:`quick_tutorial` a try.
12
fa9291 13 If you would prefer to cut and paste the example code in this tour you may browse the source code located in the `Pyramid repository in the directory "docs/quick_tour" <https://github.com/Pylons/pyramid/>`. If you have downloaded the source code, you will find the tour in the same location.
9b7f4d 14
b731b5 15 Installation
71b83e 16 ============
83fefb 17
257ac0 18 Once you have a standard Python environment setup, getting started with Pyramid
SP 19 is a breeze. Unfortunately "standard" is not so simple in Python. For this
556258 20 Quick Tour, it means `Python <https://www.python.org/downloads/>`_, `venv
SP 21 <https://packaging.python.org/en/latest/projects/#venv>`_ (or `virtualenv for
22 Python 2.7 <https://packaging.python.org/en/latest/projects/#virtualenv>`_),
23 `pip <https://packaging.python.org/en/latest/projects/#pip>`_, and `setuptools
24 <https://packaging.python.org/en/latest/projects/#easy-install>`_.
9b7f4d 25
ebbe68 26 To save a little bit of typing and to be certain that we use the modules,
SP 27 scripts, and packages installed in our virtual environment, we'll set an
28 environment variable, too.
29
c8a5e0 30 As an example, for Python 3.6+ on Linux:
83fefb 31
ebca90 32 .. parsed-literal::
83fefb 33
ebbe68 34     # set an environment variable to where you want your virtual environment
SP 35     $ export VENV=~/env
36     # create the virtual environment
37     $ python3 -m venv $VENV
38     # install pyramid
39     $ $VENV/bin/pip install pyramid
556258 40     # or for a specific released version
ebbe68 41     $ $VENV/bin/pip install "pyramid==\ |release|\ "
83fefb 42
b731b5 43 For Windows:
9b7f4d 44
ebca90 45 .. parsed-literal::
9b7f4d 46
ebbe68 47     # set an environment variable to where you want your virtual environment
108121 48     c:\\> set VENV=c:\\env
ebbe68 49     # create the virtual environment
b730ae 50     c:\\> python -m venv %VENV%
ebbe68 51     # install pyramid
SP 52     c:\\> %VENV%\\Scripts\\pip install pyramid
556258 53     # or for a specific released version
ebbe68 54     c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
9b7f4d 55
bdd544 56 Of course Pyramid runs fine on Python 2.7+, as do the examples in this *Quick
ebbe68 57 Tour*. We're showing Python 3 for simplicity. (Pyramid had production support
SP 58 for Python 3 in October 2011.) Also for simplicity, the remaining examples will
59 show only UNIX commands.
bf84d9 60
2033ee 61 .. seealso:: See also:
b731b5 62     :ref:`Quick Tutorial section on Requirements <qtut_requirements>`,
21f2b6 63     :ref:`installing_unix`, :ref:`Before You Install <installing_chapter>`,
SP 64     :ref:`Why use $VENV/bin/pip instead of source bin/activate, then pip
65     <venv-bin-pip-vs-source-bin-activate>`, and
257ac0 66     :ref:`Installing Pyramid on a Windows System <installing_windows>`.
SP 67
71b83e 68
PE 69 Hello World
70 ===========
47eaa1 71
257ac0 72 Microframeworks have shown that learning starts best from a very small first
SP 73 step. Here's a tiny application in Pyramid:
47eaa1 74
ae9014 75 .. literalinclude:: quick_tour/hello_world/app.py
71b83e 76     :linenos:
da42d5 77     :language: python
47eaa1 78
PE 79 This simple example is easy to run. Save this as ``app.py`` and run it:
80
81 .. code-block:: bash
82
ebbe68 83     $ $VENV/bin/python ./app.py
47eaa1 84
1273d0 85 Next open http://localhost:6543/ in a browser, and you will see the ``Hello
SP 86 World!`` message.
47eaa1 87
58febc 88 New to Python web programming? If so, some lines in the module merit
71b83e 89 explanation:
47eaa1 90
257ac0 91 #. *Line 10*. ``if __name__ == '__main__':`` is Python's way of saying "Start
SP 92    here when running from the command line".
47eaa1 93
d91e5d 94 #. *Lines 11-13*. Use Pyramid's :term:`configurator` in a :term:`context manager` to connect :term:`view`
257ac0 95    code to a particular URL :term:`route`.
47eaa1 96
257ac0 97 #. *Lines 6-7*. Implement the view code that generates the :term:`response`.
47eaa1 98
71b83e 99 #. *Lines 14-16*. Publish a :term:`WSGI` app using an HTTP server.
47eaa1 100
257ac0 101 As shown in this example, the :term:`configurator` plays a central role in
SP 102 Pyramid development. Building an application from loosely-coupled parts via
103 :doc:`../narr/configuration` is a central idea in Pyramid, one that we will
104 revisit regurlarly in this *Quick Tour*.
d559af 105
2033ee 106 .. seealso:: See also:
b731b5 107    :ref:`Quick Tutorial Hello World <qtut_hello_world>`,
257ac0 108    :ref:`firstapp_chapter`, and :ref:`Todo List Application in One File
SP 109    <cookbook:single-file-tutorial>`.
110
5b47ba 111
1273d0 112 Handling web requests and responses
d559af 113 ===================================
47eaa1 114
257ac0 115 Developing for the web means processing web requests. As this is a critical
SP 116 part of a web application, web developers need a robust, mature set of software
117 for web requests.
47eaa1 118
257ac0 119 Pyramid has always fit nicely into the existing world of Python web development
d5b5d0 120 (virtual environments, packaging, cookiecutters, one of the first to embrace
257ac0 121 Python 3, etc.). Pyramid turned to the well-regarded :term:`WebOb` Python
SP 122 library for request and response handling. In our example above, Pyramid hands
123 ``hello_world`` a ``request`` that is :ref:`based on WebOb <webob_chapter>`.
47eaa1 124
71b83e 125 Let's see some features of requests and responses in action:
PE 126
ae9014 127 .. literalinclude:: quick_tour/requests/app.py
da42d5 128     :language: python
71b83e 129     :pyobject: hello_world
PE 130
257ac0 131 In this Pyramid view, we get the URL being visited from ``request.url``. Also
1273d0 132 if you visited http://localhost:6543/?name=alice in a browser, the name is
ebbe68 133 included in the body of the response:
SP 134
135 .. code-block:: text
71b83e 136
d559af 137   URL http://localhost:6543/?name=alice with name: alice
PE 138
257ac0 139 Finally we set the response's content type, and return the Response.
5b47ba 140
2033ee 141 .. seealso:: See also:
257ac0 142     :ref:`Quick Tutorial Request and Response <qtut_request_response>` and
SP 143     :ref:`webob_chapter`.
144
71b83e 145
PE 146 Views
147 =====
148
257ac0 149 For the examples above, the ``hello_world`` function is a "view". In Pyramid
SP 150 views are the primary way to accept web requests and return responses.
71b83e 151
d559af 152 So far our examples place everything in one file:
PE 153
154 - the view function
155
156 - its registration with the configurator
157
1273d0 158 - the route to map it to an URL
d559af 159
PE 160 - the WSGI application launcher
161
257ac0 162 Let's move the views out to their own ``views.py`` module and change the
SP 163 ``app.py`` to scan that module, looking for decorators that set up the views.
1273d0 164
257ac0 165 First our revised ``app.py``:
71b83e 166
ae9014 167 .. literalinclude:: quick_tour/views/app.py
da42d5 168     :language: python
71b83e 169     :linenos:
PE 170
257ac0 171 We added some more routes, but we also removed the view code. Our views and
SP 172 their registrations (via decorators) are now in a module ``views.py``, which is
173 scanned via ``config.scan('views')``.
71b83e 174
257ac0 175 We now have a ``views.py`` module that is focused on handling requests and
SP 176 responses:
71b83e 177
ae9014 178 .. literalinclude:: quick_tour/views/views.py
da42d5 179     :language: python
71b83e 180     :linenos:
PE 181
1273d0 182 We have four views, each leading to the other. If you start at
257ac0 183 http://localhost:6543/, you get a response with a link to the next view. The
SP 184 ``hello_view`` (available at the URL ``/howdy``) has a link to the
185 ``redirect_view``, which issues a redirect to the final view.
65d171 186
257ac0 187 Earlier we saw ``config.add_view`` as one way to configure a view. This section
SP 188 introduces ``@view_config``. Pyramid's configuration supports :term:`imperative
189 configuration`, such as the ``config.add_view`` in the previous example. You
190 can also use :term:`declarative configuration` in which a Python
191 :term:`decorator` is placed on the line above the view. Both approaches result
192 in the same final configuration, thus usually it is simply a matter of taste.
71b83e 193
2033ee 194 .. seealso:: See also:
257ac0 195    :ref:`Quick Tutorial Views <qtut_views>`, :doc:`../narr/views`,
SP 196    :doc:`../narr/viewconfig`, and :ref:`debugging_view_configuration`.
197
71b83e 198
d559af 199 Routing
PE 200 =======
71b83e 201
257ac0 202 Writing web applications usually means sophisticated URL design. We just saw
SP 203 some Pyramid machinery for requests and views. Let's look at features that help
204 with routing.
47eaa1 205
d559af 206 Above we saw the basics of routing URLs to views in Pyramid:
47eaa1 207
257ac0 208 - Your project's "setup" code registers a route name to be used when matching
SP 209   part of the URL.
47eaa1 210
257ac0 211 - Elsewhere a view is configured to be called for that route name.
47eaa1 212
d559af 213 .. note::
47eaa1 214
257ac0 215     Why do this twice? Other Python web frameworks let you create a route and
SP 216     associate it with a view in one step. As illustrated in
217     :ref:`routes_need_ordering`, multiple routes might match the same URL
218     pattern. Rather than provide ways to help guess, Pyramid lets you be
219     explicit in ordering. Pyramid also gives facilities to avoid the problem.
d559af 220
257ac0 221 What if we want part of the URL to be available as data in my view? We can use
SP 222 this route declaration, for example:
47eaa1 223
ae9014 224 .. literalinclude:: quick_tour/routing/app.py
da42d5 225     :language: python
257ac0 226     :linenos:
SP 227     :lines: 6
228     :lineno-start: 6
47eaa1 229
257ac0 230 With this, URLs such as ``/howdy/amy/smith`` will assign ``amy`` to ``first``
SP 231 and ``smith`` to ``last``. We can then use this data in our view:
47eaa1 232
ae9014 233 .. literalinclude:: quick_tour/routing/views.py
da42d5 234     :language: python
257ac0 235     :linenos:
SP 236     :lines: 5-8
237     :lineno-start: 5
238     :emphasize-lines: 3
47eaa1 239
257ac0 240 ``request.matchdict`` contains values from the URL that match the "replacement
SP 241 patterns" (the curly braces) in the route declaration. This information can
242 then be used in your view.
47eaa1 243
2033ee 244 .. seealso:: See also:
257ac0 245    :ref:`Quick Tutorial Routing <qtut_routing>`, :doc:`../narr/urldispatch`,
SP 246    :ref:`debug_routematch_section`, and :doc:`../narr/router`.
247
71b83e 248
d559af 249 Templating
PE 250 ==========
71b83e 251
257ac0 252 Ouch. We have been making our own ``Response`` and filling the response body
SP 253 with HTML. You usually won't embed an HTML string directly in Python, but
254 instead you will use a templating language.
47eaa1 255
257ac0 256 Pyramid doesn't mandate a particular database system, form library, and so on.
SP 257 It encourages replaceability. This applies equally to templating, which is
258 fortunate: developers have strong views about template languages. That said,
259 the Pylons Project officially supports bindings for Chameleon, Jinja2, and
260 Mako. In this step let's use Chameleon.
47eaa1 261
039d12 262 Let's add ``pyramid_chameleon``, a Pyramid :term:`add-on` which enables
257ac0 263 Chameleon as a :term:`renderer` in our Pyramid application:
561a7e 264
HH 265 .. code-block:: bash
266
ebbe68 267     $ $VENV/bin/pip install pyramid_chameleon
561a7e 268
257ac0 269 With the package installed, we can include the template bindings into our
SP 270 configuration in ``app.py``:
561a7e 271
257ac0 272 .. literalinclude:: quick_tour/templating/app.py
da42d5 273     :language: python
257ac0 274     :linenos:
SP 275     :lines: 6-8
276     :lineno-start: 6
277     :emphasize-lines: 2
561a7e 278
257ac0 279 Now lets change our ``views.py`` file:
561a7e 280
ae9014 281 .. literalinclude:: quick_tour/templating/views.py
da42d5 282     :language: python
257ac0 283     :linenos:
SP 284     :emphasize-lines: 4,6
d559af 285
257ac0 286 Ahh, that looks better. We have a view that is focused on Python code. Our
SP 287 ``@view_config`` decorator specifies a :term:`renderer` that points to our
288 template file. Our view then simply returns data which is then supplied to our
289 template ``hello_world.pt``:
d559af 290
ae9014 291 .. literalinclude:: quick_tour/templating/hello_world.pt
d559af 292     :language: html
PE 293
257ac0 294 Since our view returned ``dict(name=request.matchdict['name'])``, we can use
SP 295 ``name`` as a variable in our template via ``${name}``.
5b47ba 296
2033ee 297 .. seealso:: See also:
b731b5 298     :ref:`Quick Tutorial Templating <qtut_templating>`,
257ac0 299     :doc:`../narr/templates`, :ref:`debugging_templates`, and
SP 300     :ref:`available_template_system_bindings`.
d559af 301
PE 302
257ac0 303 Templating with Jinja2
SP 304 ======================
305
306 We just said Pyramid doesn't prefer one templating language over another. Time
307 to prove it. Jinja2 is a popular templating system, modeled after Django's
308 templates. Let's add ``pyramid_jinja2``, a Pyramid :term:`add-on` which enables
309 Jinja2 as a :term:`renderer` in our Pyramid applications:
47eaa1 310
PE 311 .. code-block:: bash
312
ebbe68 313     $ $VENV/bin/pip install pyramid_jinja2
47eaa1 314
257ac0 315 With the package installed, we can include the template bindings into our
SP 316 configuration:
47eaa1 317
257ac0 318 .. literalinclude:: quick_tour/jinja2/app.py
da42d5 319     :language: python
257ac0 320     :linenos:
SP 321     :lines: 6-8
322     :lineno-start: 6
323     :emphasize-lines: 2
47eaa1 324
58febc 325 The only change in our view is to point the renderer at the ``.jinja2`` file:
47eaa1 326
ae9014 327 .. literalinclude:: quick_tour/jinja2/views.py
da42d5 328     :language: python
257ac0 329     :linenos:
SP 330     :lines: 4-6
331     :lineno-start: 4
332     :emphasize-lines: 1
47eaa1 333
d559af 334 Our Jinja2 template is very similar to our previous template:
47eaa1 335
ae9014 336 .. literalinclude:: quick_tour/jinja2/hello_world.jinja2
ebca90 337     :language: html
47eaa1 338
d559af 339 Pyramid's templating add-ons register a new kind of renderer into your
257ac0 340 application. The renderer registration maps to different kinds of filename
SP 341 extensions. In this case, changing the extension from ``.pt`` to ``.jinja2``
342 passed the view response through the ``pyramid_jinja2`` renderer.
47eaa1 343
2033ee 344 .. seealso:: See also:
257ac0 345     :ref:`Quick Tutorial Jinja2 <qtut_jinja2>`, `Jinja2 homepage
SP 346     <http://jinja.pocoo.org/>`_, and :ref:`pyramid_jinja2 Overview
347     <jinja2:overview>`.
348
47eaa1 349
1273d0 350 Static assets
47eaa1 351 =============
PE 352
257ac0 353 Of course the Web is more than just markup. You need static assets: CSS, JS,
SP 354 and images. Let's point our web app at a directory from which Pyramid will
355 serve some static assets. First let's make another call to the
715ec5 356 :term:`configurator` in ``app.py``:
47eaa1 357
ae9014 358 .. literalinclude:: quick_tour/static_assets/app.py
715ec5 359     :language: python
257ac0 360     :linenos:
SP 361     :lines: 6-8
362     :lineno-start: 6
363     :emphasize-lines: 2
47eaa1 364
PE 365 This tells our WSGI application to map requests under
257ac0 366 http://localhost:6543/static/ to files and directories inside a ``static``
SP 367 directory alongside our Python module.
47eaa1 368
1273d0 369 Next make a directory named ``static``, and place ``app.css`` inside:
47eaa1 370
ae9014 371 .. literalinclude:: quick_tour/static_assets/static/app.css
d559af 372     :language: css
47eaa1 373
257ac0 374 All we need to do now is point to it in the ``<head>`` of our Jinja2 template,
SP 375 ``hello_world.jinja2``:
47eaa1 376
715ec5 377 .. literalinclude:: quick_tour/static_assets/hello_world_static.jinja2
257ac0 378     :language: jinja
SP 379     :linenos:
380     :lines: 4-6
381     :lineno-start: 4
382     :emphasize-lines: 2
47eaa1 383
257ac0 384 This link presumes that our CSS is at a URL starting with ``/static/``. What if
SP 385 the site is later moved under ``/somesite/static/``? Or perhaps a web developer
386 changes the arrangement on disk? Pyramid provides a helper to allow flexibility
387 on URL generation:
d559af 388
715ec5 389 .. literalinclude:: quick_tour/static_assets/hello_world.jinja2
257ac0 390     :language: jinja
SP 391     :linenos:
392     :lines: 4-6
393     :lineno-start: 4
394     :emphasize-lines: 2
d559af 395
715ec5 396 By using ``request.static_url`` to generate the full URL to the static assets,
SP 397 you ensure that you stay in sync with the configuration and gain refactoring
398 flexibility later.
47eaa1 399
2033ee 400 .. seealso:: See also:
b731b5 401     :ref:`Quick Tutorial Static Assets <qtut_static_assets>`,
257ac0 402     :doc:`../narr/assets`, :ref:`preventing_http_caching`, and
SP 403     :ref:`influencing_http_caching`.
404
5b47ba 405
47eaa1 406 Returning JSON
PE 407 ==============
408
257ac0 409 Modern web apps are more than rendered HTML. Dynamic pages now use JavaScript
SP 410 to update the UI in the browser by requesting server data as JSON. Pyramid
411 supports this with a JSON renderer:
47eaa1 412
ae9014 413 .. literalinclude:: quick_tour/json/views.py
da42d5 414     :language: python
257ac0 415     :linenos:
SP 416     :lines: 9-
417     :lineno-start: 9
47eaa1 418
257ac0 419 This wires up a view that returns some data through the JSON :term:`renderer`,
SP 420 which calls Python's JSON support to serialize the data into JSON, and sets the
421 appropriate HTTP headers.
422
423 We also need to add a route to ``app.py`` so that our app will know how to
424 respond to a request for ``hello.json``.
425
426 .. literalinclude:: quick_tour/json/app.py
da42d5 427     :language: python
257ac0 428     :linenos:
SP 429     :lines: 6-8
430     :lineno-start: 6
431     :emphasize-lines: 2
5b47ba 432
2033ee 433 .. seealso:: See also:
257ac0 434     :ref:`Quick Tutorial JSON <qtut_json>`, :ref:`views_which_use_a_renderer`,
SP 435     :ref:`json_renderer`, and :ref:`adding_and_overriding_renderers`.
436
47eaa1 437
1273d0 438 View classes
47eaa1 439 ============
PE 440
257ac0 441 So far our views have been simple, free-standing functions. Many times your
SP 442 views are related. They may have different ways to look at or work on the same
443 data, or they may be a REST API that handles multiple operations. Grouping
444 these together as a :ref:`view class <class_as_view>` makes sense and achieves
445 the following goals.
47eaa1 446
65d171 447 - Group views
47eaa1 448
65d171 449 - Centralize some repetitive defaults
47eaa1 450
65d171 451 - Share some state and helpers
47eaa1 452
257ac0 453 The following shows a "Hello World" example with three operations: view a form,
SP 454 save a change, or press the delete button in our ``views.py``:
47eaa1 455
ae9014 456 .. literalinclude:: quick_tour/view_classes/views.py
da42d5 457     :language: python
257ac0 458     :linenos:
SP 459     :lines: 7-
460     :lineno-start: 7
47eaa1 461
257ac0 462 As you can see, the three views are logically grouped together. Specifically:
47eaa1 463
257ac0 464 - The first view is returned when you go to ``/howdy/amy``. This URL is mapped
SP 465   to the ``hello`` route that we centrally set using the optional
65d171 466   ``@view_defaults``.
47eaa1 467
65d171 468 - The second view is returned when the form data contains a field with
257ac0 469   ``form.edit``, such as clicking on ``<input type="submit" name="form.edit"
SP 470   value="Save">``. This rule is specified in the ``@view_config`` for that
471   view.
d559af 472
257ac0 473 - The third view is returned when clicking on a button such as ``<input
SP 474   type="submit" name="form.delete" value="Delete">``.
d559af 475
257ac0 476 Only one route is needed, stated in one place atop the view class. Also, the
SP 477 assignment of ``name`` is done in the ``__init__`` function. Our templates can
478 then use ``{{ view.name }}``.
5b47ba 479
257ac0 480 Pyramid view classes, combined with built-in and custom predicates, have much
SP 481 more to offer:
b731b5 482
PE 483 - All the same view configuration parameters as function views
484
257ac0 485 - One route leading to multiple views, based on information in the request or
SP 486   data such as ``request_param``, ``request_method``, ``accept``, ``header``,
487   ``xhr``, ``containment``, and ``custom_predicates``
b731b5 488
2033ee 489 .. seealso:: See also:
257ac0 490     :ref:`Quick Tutorial View Classes <qtut_view_classes>`, :ref:`Quick
SP 491     Tutorial More View Classes <qtut_more_view_classes>`, and
492     :ref:`class_as_view`.
493
47eaa1 494
a0ebd7 495 Quick project startup with cookiecutters
SP 496 ========================================
47eaa1 497
5cf8c3 498 So far we have done all of our *Quick Tour* as a single Python file. No Python
SP 499 packages, no structure. Most Pyramid projects, though, aren't developed this
500 way.
47eaa1 501
2cd1ea 502 To ease the process of getting started, the Pylons Project provides :term:`cookiecutter`\ s that generate sample Pyramid projects from project templates. These cookiecutters will install Pyramid and its dependencies as well.
a0ebd7 503
SP 504 First you'll need to install cookiecutter.
47eaa1 505
PE 506 .. code-block:: bash
507
a0ebd7 508     $ $VENV/bin/pip install cookiecutter
47eaa1 509
2cd1ea 510 Let's use the cookiecutter ``pyramid-cookiecutter-starter`` to create a starter Pyramid project in the current directory, entering values at the prompts as shown below for the following command.
47eaa1 511
PE 512 .. code-block:: bash
513
1aa283 514     $ $VENV/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.9-branch
47eaa1 515
a0ebd7 516 If prompted for the first item, accept the default ``yes`` by hitting return.
SP 517
2cd381 518 .. code-block:: text
SP 519
520     You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
521     Is it okay to delete and re-clone it? [yes]: yes
522     project_name [Pyramid Scaffold]: hello_world
6ff6fa 523     repo_name [hello_world]: hello_world
2cd381 524     Select template_language:
SP 525     1 - jinja2
526     2 - chameleon
6204d8 527     3 - mako
SP 528     Choose from 1, 2, 3 [1]: 1
a0ebd7 529
b488f7 530 We then run through the following commands.
47eaa1 531
PE 532 .. code-block:: bash
533
a0ebd7 534     # Change directory into your newly created project.
2cd1ea 535     $ cd hello_world
a0ebd7 536     # Create a new virtual environment...
SP 537     $ python3 -m venv env
538     # ...where we upgrade packaging tools...
539     $ env/bin/pip install --upgrade pip setuptools
540     # ...and into which we install our project and its testing requirements.
541     $ env/bin/pip install -e ".[testing]"
2cd1ea 542     # Reset our environment variable for a new virtual environment.
b488f7 543     $ export VENV=~/hello_world/env
47eaa1 544
5cf8c3 545 We are moving in the direction of a full-featured Pyramid project, with a
SP 546 proper setup for Python standards (packaging) and Pyramid configuration. This
547 includes a new way of running your application:
47eaa1 548
PE 549 .. code-block:: bash
550
ebbe68 551     $ $VENV/bin/pserve development.ini
47eaa1 552
PE 553 Let's look at ``pserve`` and configuration in more depth.
5b47ba 554
2033ee 555 .. seealso:: See also:
49cd00 556     :ref:`Quick Tutorial Cookiecutters <qtut_cookiecutters>`,
b731b5 557     :ref:`project_narr`, and
d5b5d0 558     :doc:`../narr/cookiecutters`
47eaa1 559
1273d0 560 Application running with ``pserve``
47eaa1 561 ===================================
PE 562
2cd1ea 563 Prior to the cookiecutter, our project mixed a number of operational details into our
5cf8c3 564 code. Why should my main code care which HTTP server I want and what port
SP 565 number to run on?
d4bd29 566
5cf8c3 567 ``pserve`` is Pyramid's application runner, separating operational details from
SP 568 your code. When you install Pyramid, a small command program called ``pserve``
569 is written to your ``bin`` directory. This program is an executable Python
570 module. It's very small, getting most of its brains via import.
47eaa1 571
5cf8c3 572 You can run ``pserve`` with ``--help`` to see some of its options. Doing so
SP 573 reveals that you can ask ``pserve`` to watch your development files and reload
574 the server when they change:
47eaa1 575
PE 576 .. code-block:: bash
577
ebbe68 578     $ $VENV/bin/pserve development.ini --reload
47eaa1 579
5cf8c3 580 The ``pserve`` command has a number of other options and operations. Most of
SP 581 the work, though, comes from your project's wiring, as expressed in the
582 configuration file you supply to ``pserve``. Let's take a look at this
583 configuration file.
49d634 584
2033ee 585 .. seealso:: See also:
b731b5 586     :ref:`what_is_this_pserve_thing`
47eaa1 587
1273d0 588 Configuration with ``.ini`` files
47eaa1 589 =================================
PE 590
5cf8c3 591 Earlier in *Quick Tour* we first met Pyramid's configuration system. At that
SP 592 point we did all configuration in Python code. For example, the port number
2cd1ea 593 chosen for our HTTP server was right there in Python code. Our cookiecutter has
5cf8c3 594 moved this decision and more into the ``development.ini`` file:
d4bd29 595
ae9014 596 .. literalinclude:: quick_tour/package/development.ini
d4bd29 597     :language: ini
47eaa1 598
5cf8c3 599 Let's take a quick high-level look. First the ``.ini`` file is divided into
SP 600 sections:
47eaa1 601
5cf8c3 602 - ``[app:main]`` configures our WSGI app
47eaa1 603
PE 604 - ``[server:main]`` holds our WSGI server settings
605
606 - Various sections afterwards configure our Python logging system
607
d4bd29 608 We have a few decisions made for us in this configuration:
47eaa1 609
1273d0 610 #. *WSGI app:* What package has our WSGI application in it?
5cf8c3 611    ``use = egg:hello_world`` in the app section tells the configuration what
SP 612    application to load.
47eaa1 613
1273d0 614 #. *Easier development by automatic template reloading:* In development mode,
SP 615    you shouldn't have to restart the server when editing a Jinja2 template.
5cf8c3 616    ``pyramid.reload_templates = true`` sets this policy, which might be
SP 617    different in production.
47eaa1 618
785776 619 #. *Choice of web server:* ``use = egg:waitress#main`` tells ``pserve`` to
SP 620    use the ``waitress`` server.
621
6d120e 622 #. *Interfaces:* ``listen = localhost:6543`` tells ``waitress`` to listen on all interfaces on port 6543 for both IPv4 and IPv6.
785776 623
d5b5d0 624 Additionally the ``development.ini`` generated by this cookiecutter wired up
5cf8c3 625 Python's standard logging. We'll now see in the console, for example, a log on
SP 626 every request that comes in, as well as traceback information.
47eaa1 627
2033ee 628 .. seealso:: See also:
b731b5 629     :ref:`Quick Tutorial Application Configuration <qtut_ini>`,
PE 630     :ref:`environment_chapter` and
631     :doc:`../narr/paste`
49d634 632
5b47ba 633
1273d0 634 Easier development with ``debugtoolbar``
47eaa1 635 ========================================
PE 636
58febc 637 As we introduce the basics, we also want to show how to be productive in
5cf8c3 638 development and debugging. For example, we just discussed template reloading
SP 639 and earlier we showed ``--reload`` for application reloading.
47eaa1 640
5cf8c3 641 ``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes several tools
SP 642 available in your browser. Adding it to your project illustrates several points
643 about configuration.
47eaa1 644
af1e32 645 The cookiecutter ``pyramid-cookiecutter-starter`` already configured our package to include the
5cf8c3 646 add-on ``pyramid_debugtoolbar`` in its ``setup.py``:
47eaa1 647
ae9014 648 .. literalinclude:: quick_tour/package/setup.py
5cf8c3 649     :language: python
af1e32 650     :lineno-match:
65a6d3 651     :lines: 11-17
SP 652     :emphasize-lines: 5
47eaa1 653
5cf8c3 654 It was installed when you previously ran:
47eaa1 655
PE 656 .. code-block:: bash
657
af1e32 658     $ $VENV/bin/pip install -e ".[testing]"
47eaa1 659
5cf8c3 660 The ``pyramid_debugtoolbar`` package is a Pyramid add-on, which means we need
65a6d3 661 to include its configuration into our web application. The cookiecutter already took care of this for us in its ``development.ini`` using the ``pyramid.includes`` facility:
47eaa1 662
ae9014 663 .. literalinclude:: quick_tour/package/development.ini
d4bd29 664     :language: ini
af1e32 665     :lineno-match:
SP 666     :lines: 14-15
47eaa1 667
5cf8c3 668 You'll now see a Pyramid logo on the right side of your browser window, which
SP 669 when clicked opens a new window that provides introspective access to debugging
670 information. Even better, if your web application generates an error, you will
671 see a nice traceback on the screen. When you want to disable this toolbar,
672 there's no need to change code: you can remove it from ``pyramid.includes`` in
673 the relevant ``.ini`` configuration file.
5b47ba 674
2033ee 675 .. seealso:: See also:
5cf8c3 676     :ref:`Quick Tutorial pyramid_debugtoolbar <qtut_debugtoolbar>` and
b731b5 677     :ref:`pyramid_debugtoolbar <toolbar:overview>`
47eaa1 678
ebbe68 679 Unit tests and ``py.test``
SP 680 ==========================
47eaa1 681
5cf8c3 682 Yikes! We got this far and we haven't yet discussed tests. This is particularly
SP 683 egregious, as Pyramid has had a deep commitment to full test coverage since
684 before its release.
47eaa1 685
948344 686 Our ``pyramid-cookiecutter-starter`` cookiecutter generated a ``tests.py`` module with
SP 687 one unit test and one functional test in it. It also configured ``setup.py`` with test requirements:
371d11 688 ``py.test`` as the test runner, ``WebTest`` for running view tests, and the
65a6d3 689 ``pytest-cov`` tool which yells at us for code that isn't tested:
47eaa1 690
948344 691 .. literalinclude:: quick_tour/package/setup.py
SP 692     :language: python
693     :lineno-match:
65a6d3 694     :lines: 19-23
47eaa1 695
948344 696 .. literalinclude:: quick_tour/package/setup.py
SP 697     :language: python
698     :lineno-match:
65a6d3 699     :lines: 43-45
47eaa1 700
948344 701 We already installed the test requirements when we ran the command ``$VENV/bin/pip install -e ".[testing]"``. We can now run all our tests:
47eaa1 702
PE 703 .. code-block:: bash
704
683d75 705     $ $VENV/bin/py.test --cov --cov-report=term-missing
47eaa1 706
ebbe68 707 This yields the following output.
47eaa1 708
ebbe68 709 .. code-block:: text
SP 710
711     =========================== test session starts ===========================
948344 712     platform darwin -- Python 3.6.0, pytest-3.0.5, py-1.4.32, pluggy-0.4.0
SP 713     rootdir: /Users/stevepiercy/hello_world, inifile: pytest.ini
714     plugins: cov-2.4.0
715     collected 2 items
ebbe68 716
948344 717     hello_world/tests.py ..
SP 718
c8a5e0 719     ------------- coverage: platform darwin, python 3.6.0-final-0 -------------
948344 720     Name                                      Stmts   Miss  Cover   Missing
SP 721     -----------------------------------------------------------------------
722     hello_world/__init__.py                       8      0   100%
723     hello_world/views.py                          3      0   100%
724     -----------------------------------------------------------------------
725     TOTAL                                        11      0   100%
ebbe68 726
SP 727
948344 728     ========================= 2 passed in 1.37 seconds =========================
SP 729
730 Our tests passed, and its coverage is complete. What did our test look like?
47eaa1 731
ae9014 732 .. literalinclude:: quick_tour/package/hello_world/tests.py
da42d5 733     :language: python
5cf8c3 734     :linenos:
47eaa1 735
5cf8c3 736 Pyramid supplies helpers for test writing, which we use in the test setup and
948344 737 teardown. Our first test imports the view, makes a dummy request, and sees if the
SP 738 view returns what we expected. Our second test verifies that the response body from a request to the web root contains what we expected.
47eaa1 739
2033ee 740 .. seealso:: See also:
5cf8c3 741     :ref:`Quick Tutorial Unit Testing <qtut_unit_testing>`, :ref:`Quick
SP 742     Tutorial Functional Testing <qtut_functional_testing>`, and
b731b5 743     :ref:`testing_chapter`
5b47ba 744
83fefb 745 Logging
PE 746 =======
747
5cf8c3 748 It's important to know what is going on inside our web application. In
SP 749 development we might need to collect some output. In production we might need
750 to detect situations when other people use the site. We need *logging*.
83fefb 751
c87565 752 Fortunately Pyramid uses the normal Python approach to logging. The ``development.ini`` file for your project has a number of lines that configure the
5cf8c3 753 logging for you to some reasonable defaults. You then see messages sent by
SP 754 Pyramid (for example, when a new request comes in).
83fefb 755
5cf8c3 756 Maybe you would like to log messages in your code? In your Python module,
c87565 757 import and set up the logging in your ``views.py``:
83fefb 758
c87565 759 .. literalinclude:: quick_tour/logging/hello_world/views.py
5cf8c3 760     :language: python
c87565 761     :lineno-match:
5cf8c3 762     :lines: 3-4
83fefb 763
PE 764 You can now, in your code, log messages:
765
c87565 766 .. literalinclude:: quick_tour/logging/hello_world/views.py
5cf8c3 767     :language: python
c87565 768     :lineno-match:
SP 769     :lines: 7-8
5cf8c3 770     :emphasize-lines: 2
83fefb 771
c87565 772 This will log ``Some Message`` at a ``DEBUG`` log level to the
5cf8c3 773 application-configured logger in your ``development.ini``. What controls that?
SP 774 These emphasized sections in the configuration file:
83fefb 775
c87565 776 .. literalinclude:: quick_tour/logging/development.ini
d4bd29 777     :language: ini
c87565 778     :lineno-match:
SP 779     :lines: 34-50
5cf8c3 780     :emphasize-lines: 1-2,14-17
83fefb 781
5cf8c3 782 Our application, a package named ``hello_world``, is set up as a logger and
SP 783 configured to log messages at a ``DEBUG`` or higher level. When you visit
556258 784 http://localhost:6543, your console will now show:
SP 785
786 .. code-block:: text
d4bd29 787
c87565 788     2016-12-25 03:03:57,059 DEBUG [hello_world.views:8][waitress] Some Message
5b47ba 789
2033ee 790 .. seealso:: See also:
5cf8c3 791     :ref:`Quick Tutorial Logging <qtut_logging>` and :ref:`logging_chapter`.
83fefb 792
PE 793 Sessions
794 ========
795
5cf8c3 796 When people use your web application, they frequently perform a task that
SP 797 requires semi-permanent data to be saved. For example, a shopping cart. This is
798 called a :term:`session`.
83fefb 799
5cf8c3 800 Pyramid has basic built-in support for sessions. Third party packages such as
SP 801 ``pyramid_redis_sessions`` provide richer session support. Or you can create
802 your own custom sessioning engine. Let's take a look at the :doc:`built-in
803 sessioning support <../narr/sessions>`. In our ``__init__.py`` we first import
804 the kind of sessioning we want:
83fefb 805
64009a 806 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 807     :language: python
64009a 808     :lineno-match:
SP 809     :lines: 1-2
5cf8c3 810     :emphasize-lines: 2
83fefb 811
d4bd29 812 .. warning::
83fefb 813
5cf8c3 814     As noted in the session docs, this example implementation is not intended
SP 815     for use in settings with security implications.
83fefb 816
d4bd29 817 Now make a "factory" and pass it to the :term:`configurator`'s
PE 818 ``session_factory`` argument:
83fefb 819
64009a 820 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 821     :language: python
64009a 822     :lineno-match:
SP 823     :lines: 10-13
824     :emphasize-lines: 2-3
83fefb 825
5cf8c3 826 Pyramid's :term:`request` object now has a ``session`` attribute that we can
SP 827 use in our view code in ``views.py``:
83fefb 828
64009a 829 .. literalinclude:: quick_tour/sessions/hello_world/views.py
5cf8c3 830     :language: python
64009a 831     :lineno-match:
SP 832     :lines: 7-
5cf8c3 833     :emphasize-lines: 3-7
83fefb 834
64009a 835 We need to update our Jinja2 template ``templates/mytemplate.jinja2`` to show counter increment in the session:
d4bd29 836
64009a 837 .. literalinclude:: quick_tour/sessions/hello_world/templates/mytemplate.jinja2
d4bd29 838     :language: jinja
64009a 839     :lineno-match:
SP 840     :lines: 4-8
841     :emphasize-lines: 4
d4bd29 842
2033ee 843 .. seealso:: See also:
5cf8c3 844     :ref:`Quick Tutorial Sessions <qtut_sessions>`, :ref:`sessions_chapter`,
SP 845     :ref:`flash_messages`, :ref:`session_module`, and
846     :term:`pyramid_redis_sessions`.
83fefb 847
PE 848
849 Databases
850 =========
851
6a9366 852 Web applications mean data. Data means databases. Frequently SQL databases. SQL
SP 853 databases frequently mean an "ORM" (object-relational mapper.) In Python, ORM
854 usually leads to the mega-quality *SQLAlchemy*, a Python package that greatly
855 eases working with databases.
83fefb 856
b488f7 857 Pyramid and SQLAlchemy are great friends. That friendship includes a cookiecutter!
83fefb 858
PE 859 .. code-block:: bash
860
b488f7 861     $ cd ~
1aa283 862     $ env/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-alchemy --checkout 1.9-branch
b488f7 863
SP 864 If prompted for the first item, accept the default ``yes`` by hitting return.
865
2cd381 866 .. code-block:: text
SP 867
868     You've cloned ~/.cookiecutters/pyramid-cookiecutter-alchemy before.
869     Is it okay to delete and re-clone it? [yes]: yes
870     project_name [Pyramid Scaffold]: sqla_demo
6ff6fa 871     repo_name [sqla_demo]: sqla_demo
b488f7 872
SP 873 We then run through the following commands as before.
874
875 .. code-block:: bash
876
877     # Change directory into your newly created project.
878     $ cd sqla_demo
879     # Create a new virtual environment...
880     $ python3 -m venv env
881     # ...where we upgrade packaging tools...
882     $ env/bin/pip install --upgrade pip setuptools
883     # ...and into which we install our project and its testing requirements.
884     $ env/bin/pip install -e ".[testing]"
885     # Reset our environment variable for a new virtual environment.
886     $ export VENV=~/sqla_demo/env
83fefb 887
6a9366 888 We now have a working sample SQLAlchemy application with all dependencies
SP 889 installed. The sample project provides a console script to initialize a SQLite
890 database with tables. Let's run it, then start the application:
83fefb 891
PE 892 .. code-block:: bash
893
ebbe68 894   $ $VENV/bin/initialize_sqla_demo_db development.ini
SP 895   $ $VENV/bin/pserve development.ini
83fefb 896
6a9366 897 The ORM eases the mapping of database structures into a programming language.
d5b5d0 898 SQLAlchemy uses "models" for this mapping. The cookiecutter generated a sample
6a9366 899 model:
83fefb 900
414b67 901 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py
da42d5 902     :language: python
b488f7 903     :lineno-match:
SP 904     :pyobject: MyModel
83fefb 905
6a9366 906 View code, which mediates the logic between web requests and the rest of the
SP 907 system, can then easily get at the data thanks to SQLAlchemy:
83fefb 908
3eb1c3 909 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py
da42d5 910     :language: python
b488f7 911     :lineno-match:
SP 912     :lines: 13
5b47ba 913
2033ee 914 .. seealso:: See also:
6a9366 915     :ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy
SP 916     <http://www.sqlalchemy.org/>`_, :ref:`making_a_console_script`,
917     :ref:`bfg_sql_wiki_tutorial`, and :ref:`Application Transactions with
918     pyramid_tm <tm:overview>`.
919
47eaa1 920
83fefb 921 Forms
PE 922 =====
47eaa1 923
6a9366 924 Developers have lots of opinions about web forms, thus there are many form
SP 925 libraries for Python. Pyramid doesn't directly bundle a form library, but
926 *Deform* is a popular choice for forms, along with its related *Colander*
927 schema system.
47eaa1 928
6a9366 929 As an example, imagine we want a form that edits a wiki page. The form should
SP 930 have two fields on it, one of them a required title and the other a rich text
931 editor for the body. With Deform we can express this as a Colander schema:
83fefb 932
d4bd29 933 .. code-block:: python
PE 934
935     class WikiPage(colander.MappingSchema):
936         title = colander.SchemaNode(colander.String())
937         body = colander.SchemaNode(
938             colander.String(),
939             widget=deform.widget.RichTextWidget()
940         )
941
6a9366 942 With this in place, we can render the HTML for a form, perhaps with form data
SP 943 from an existing page:
d4bd29 944
PE 945 .. code-block:: python
946
947     form = self.wiki_form.render()
948
949 We'd like to handle form submission, validation, and saving:
950
951 .. code-block:: python
952
953     # Get the form data that was posted
954     controls = self.request.POST.items()
955     try:
956         # Validate and either raise a validation error
957         # or return deserialized data from widgets
958         appstruct = wiki_form.validate(controls)
959     except deform.ValidationFailure as e:
960         # Bail out and render form with errors
961         return dict(title=title, page=page, form=e.render())
962
963     # Change the content and redirect to the view
964     page['title'] = appstruct['title']
965     page['body'] = appstruct['body']
966
6a9366 967 Deform and Colander provide a very flexible combination for forms, widgets,
SP 968 schemas, and validation. Recent versions of Deform also include a :ref:`retail
969 mode <deform:retail>` for gaining Deform features on custom forms.
d4bd29 970
a0ad6f 971 Deform uses attractive CSS from Twitter Bootstrap and more powerful select, checkbox, and date and time widgets.
d4bd29 972
2033ee 973 .. seealso:: See also:
a0ad6f 974     :ref:`Quick Tutorial Forms <qtut_forms>`, :ref:`Deform <deform:overview>`, and :ref:`Colander <colander:overview>`.
83fefb 975
d4bd29 976 Conclusion
PE 977 ==========
83fefb 978
ae9014 979 This *Quick Tour* covered a little about a lot. We introduced a long list
PE 980 of concepts in Pyramid, many of which are expanded on more fully in the
540fcd 981 Pyramid developer docs.