LuisCastilloH
2018-05-16 dddcae3c7b5e0fb143f06b29e7d3c4d5e880b6bb
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
dddcae 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
c52517 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
257ac0 94 #. *Lines 11-13*. Use Pyramid's :term:`configurator` to connect :term:`view`
SP 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
813b7c 514     $ $VENV/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.8-branch
47eaa1 515
a0ebd7 516 If prompted for the first item, accept the default ``yes`` by hitting return.
SP 517
51a39b 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
eb3531 523     repo_name [hello_world]: hello_world
51a39b 524     Select template_language:
SP 525     1 - jinja2
526     2 - chameleon
78828f 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
12fe4f 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:
5cf8c3 651     :lines: 11-16
af1e32 652     :emphasize-lines: 4
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
af1e32 661 to include its configuration into our web application. The cookiecutter already took care of this for us in its ``__init__.py``:
47eaa1 662
ae9014 663 .. literalinclude:: quick_tour/package/hello_world/__init__.py
5cf8c3 664     :language: python
af1e32 665     :lineno-match:
SP 666     :lines: 8
47eaa1 667
5cf8c3 668 And it uses the ``pyramid.includes`` facility in our ``development.ini``:
47eaa1 669
ae9014 670 .. literalinclude:: quick_tour/package/development.ini
d4bd29 671     :language: ini
af1e32 672     :lineno-match:
SP 673     :lines: 14-15
47eaa1 674
5cf8c3 675 You'll now see a Pyramid logo on the right side of your browser window, which
SP 676 when clicked opens a new window that provides introspective access to debugging
677 information. Even better, if your web application generates an error, you will
678 see a nice traceback on the screen. When you want to disable this toolbar,
679 there's no need to change code: you can remove it from ``pyramid.includes`` in
680 the relevant ``.ini`` configuration file.
5b47ba 681
2033ee 682 .. seealso:: See also:
5cf8c3 683     :ref:`Quick Tutorial pyramid_debugtoolbar <qtut_debugtoolbar>` and
b731b5 684     :ref:`pyramid_debugtoolbar <toolbar:overview>`
47eaa1 685
ebbe68 686 Unit tests and ``py.test``
SP 687 ==========================
47eaa1 688
5cf8c3 689 Yikes! We got this far and we haven't yet discussed tests. This is particularly
SP 690 egregious, as Pyramid has had a deep commitment to full test coverage since
691 before its release.
47eaa1 692
948344 693 Our ``pyramid-cookiecutter-starter`` cookiecutter generated a ``tests.py`` module with
SP 694 one unit test and one functional test in it. It also configured ``setup.py`` with test requirements:
371d11 695 ``py.test`` as the test runner, ``WebTest`` for running view tests, and the
OO 696 ``pytest-cov`` tool which yells at us for code that isn't tested. The
697 highlighted lines show this:
47eaa1 698
948344 699 .. literalinclude:: quick_tour/package/setup.py
SP 700     :language: python
701     :lineno-match:
702     :lines: 18-22
47eaa1 703
948344 704 .. literalinclude:: quick_tour/package/setup.py
SP 705     :language: python
706     :lineno-match:
707     :lines: 42-44
47eaa1 708
948344 709 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 710
PE 711 .. code-block:: bash
712
683d75 713     $ $VENV/bin/py.test --cov --cov-report=term-missing
47eaa1 714
ebbe68 715 This yields the following output.
47eaa1 716
ebbe68 717 .. code-block:: text
SP 718
719     =========================== test session starts ===========================
948344 720     platform darwin -- Python 3.6.0, pytest-3.0.5, py-1.4.32, pluggy-0.4.0
SP 721     rootdir: /Users/stevepiercy/hello_world, inifile: pytest.ini
722     plugins: cov-2.4.0
723     collected 2 items
ebbe68 724
948344 725     hello_world/tests.py ..
SP 726
c8a5e0 727     ------------- coverage: platform darwin, python 3.6.0-final-0 -------------
948344 728     Name                                      Stmts   Miss  Cover   Missing
SP 729     -----------------------------------------------------------------------
730     hello_world/__init__.py                       8      0   100%
731     hello_world/views.py                          3      0   100%
732     -----------------------------------------------------------------------
733     TOTAL                                        11      0   100%
ebbe68 734
SP 735
948344 736     ========================= 2 passed in 1.37 seconds =========================
SP 737
738 Our tests passed, and its coverage is complete. What did our test look like?
47eaa1 739
ae9014 740 .. literalinclude:: quick_tour/package/hello_world/tests.py
da42d5 741     :language: python
5cf8c3 742     :linenos:
47eaa1 743
5cf8c3 744 Pyramid supplies helpers for test writing, which we use in the test setup and
948344 745 teardown. Our first test imports the view, makes a dummy request, and sees if the
SP 746 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 747
2033ee 748 .. seealso:: See also:
5cf8c3 749     :ref:`Quick Tutorial Unit Testing <qtut_unit_testing>`, :ref:`Quick
SP 750     Tutorial Functional Testing <qtut_functional_testing>`, and
b731b5 751     :ref:`testing_chapter`
5b47ba 752
83fefb 753 Logging
PE 754 =======
755
5cf8c3 756 It's important to know what is going on inside our web application. In
SP 757 development we might need to collect some output. In production we might need
758 to detect situations when other people use the site. We need *logging*.
83fefb 759
c87565 760 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 761 logging for you to some reasonable defaults. You then see messages sent by
SP 762 Pyramid (for example, when a new request comes in).
83fefb 763
5cf8c3 764 Maybe you would like to log messages in your code? In your Python module,
c87565 765 import and set up the logging in your ``views.py``:
83fefb 766
c87565 767 .. literalinclude:: quick_tour/logging/hello_world/views.py
5cf8c3 768     :language: python
c87565 769     :lineno-match:
5cf8c3 770     :lines: 3-4
83fefb 771
PE 772 You can now, in your code, log messages:
773
c87565 774 .. literalinclude:: quick_tour/logging/hello_world/views.py
5cf8c3 775     :language: python
c87565 776     :lineno-match:
SP 777     :lines: 7-8
5cf8c3 778     :emphasize-lines: 2
83fefb 779
c87565 780 This will log ``Some Message`` at a ``DEBUG`` log level to the
5cf8c3 781 application-configured logger in your ``development.ini``. What controls that?
SP 782 These emphasized sections in the configuration file:
83fefb 783
c87565 784 .. literalinclude:: quick_tour/logging/development.ini
d4bd29 785     :language: ini
c87565 786     :lineno-match:
SP 787     :lines: 34-50
5cf8c3 788     :emphasize-lines: 1-2,14-17
83fefb 789
5cf8c3 790 Our application, a package named ``hello_world``, is set up as a logger and
SP 791 configured to log messages at a ``DEBUG`` or higher level. When you visit
556258 792 http://localhost:6543, your console will now show:
SP 793
794 .. code-block:: text
d4bd29 795
c87565 796     2016-12-25 03:03:57,059 DEBUG [hello_world.views:8][waitress] Some Message
5b47ba 797
2033ee 798 .. seealso:: See also:
5cf8c3 799     :ref:`Quick Tutorial Logging <qtut_logging>` and :ref:`logging_chapter`.
83fefb 800
PE 801 Sessions
802 ========
803
5cf8c3 804 When people use your web application, they frequently perform a task that
SP 805 requires semi-permanent data to be saved. For example, a shopping cart. This is
806 called a :term:`session`.
83fefb 807
5cf8c3 808 Pyramid has basic built-in support for sessions. Third party packages such as
SP 809 ``pyramid_redis_sessions`` provide richer session support. Or you can create
810 your own custom sessioning engine. Let's take a look at the :doc:`built-in
811 sessioning support <../narr/sessions>`. In our ``__init__.py`` we first import
812 the kind of sessioning we want:
83fefb 813
64009a 814 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 815     :language: python
64009a 816     :lineno-match:
SP 817     :lines: 1-2
5cf8c3 818     :emphasize-lines: 2
83fefb 819
d4bd29 820 .. warning::
83fefb 821
5cf8c3 822     As noted in the session docs, this example implementation is not intended
SP 823     for use in settings with security implications.
83fefb 824
d4bd29 825 Now make a "factory" and pass it to the :term:`configurator`'s
PE 826 ``session_factory`` argument:
83fefb 827
64009a 828 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 829     :language: python
64009a 830     :lineno-match:
SP 831     :lines: 10-13
832     :emphasize-lines: 2-3
83fefb 833
5cf8c3 834 Pyramid's :term:`request` object now has a ``session`` attribute that we can
SP 835 use in our view code in ``views.py``:
83fefb 836
64009a 837 .. literalinclude:: quick_tour/sessions/hello_world/views.py
5cf8c3 838     :language: python
64009a 839     :lineno-match:
SP 840     :lines: 7-
5cf8c3 841     :emphasize-lines: 3-7
83fefb 842
64009a 843 We need to update our Jinja2 template ``templates/mytemplate.jinja2`` to show counter increment in the session:
d4bd29 844
64009a 845 .. literalinclude:: quick_tour/sessions/hello_world/templates/mytemplate.jinja2
d4bd29 846     :language: jinja
64009a 847     :lineno-match:
SP 848     :lines: 4-8
849     :emphasize-lines: 4
d4bd29 850
2033ee 851 .. seealso:: See also:
5cf8c3 852     :ref:`Quick Tutorial Sessions <qtut_sessions>`, :ref:`sessions_chapter`,
SP 853     :ref:`flash_messages`, :ref:`session_module`, and
854     :term:`pyramid_redis_sessions`.
83fefb 855
PE 856
857 Databases
858 =========
859
6a9366 860 Web applications mean data. Data means databases. Frequently SQL databases. SQL
SP 861 databases frequently mean an "ORM" (object-relational mapper.) In Python, ORM
862 usually leads to the mega-quality *SQLAlchemy*, a Python package that greatly
863 eases working with databases.
83fefb 864
b488f7 865 Pyramid and SQLAlchemy are great friends. That friendship includes a cookiecutter!
83fefb 866
PE 867 .. code-block:: bash
868
b488f7 869     $ cd ~
813b7c 870     $ env/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-alchemy --checkout 1.8-branch
b488f7 871
SP 872 If prompted for the first item, accept the default ``yes`` by hitting return.
873
51a39b 874 .. code-block:: text
SP 875
876     You've cloned ~/.cookiecutters/pyramid-cookiecutter-alchemy before.
877     Is it okay to delete and re-clone it? [yes]: yes
878     project_name [Pyramid Scaffold]: sqla_demo
eb3531 879     repo_name [sqla_demo]: sqla_demo
b488f7 880
SP 881 We then run through the following commands as before.
882
883 .. code-block:: bash
884
885     # Change directory into your newly created project.
886     $ cd sqla_demo
887     # Create a new virtual environment...
888     $ python3 -m venv env
889     # ...where we upgrade packaging tools...
890     $ env/bin/pip install --upgrade pip setuptools
891     # ...and into which we install our project and its testing requirements.
892     $ env/bin/pip install -e ".[testing]"
893     # Reset our environment variable for a new virtual environment.
894     $ export VENV=~/sqla_demo/env
83fefb 895
6a9366 896 We now have a working sample SQLAlchemy application with all dependencies
SP 897 installed. The sample project provides a console script to initialize a SQLite
898 database with tables. Let's run it, then start the application:
83fefb 899
PE 900 .. code-block:: bash
901
ebbe68 902   $ $VENV/bin/initialize_sqla_demo_db development.ini
SP 903   $ $VENV/bin/pserve development.ini
83fefb 904
6a9366 905 The ORM eases the mapping of database structures into a programming language.
d5b5d0 906 SQLAlchemy uses "models" for this mapping. The cookiecutter generated a sample
6a9366 907 model:
83fefb 908
414b67 909 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py
da42d5 910     :language: python
b488f7 911     :lineno-match:
SP 912     :pyobject: MyModel
83fefb 913
6a9366 914 View code, which mediates the logic between web requests and the rest of the
SP 915 system, can then easily get at the data thanks to SQLAlchemy:
83fefb 916
3eb1c3 917 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py
da42d5 918     :language: python
b488f7 919     :lineno-match:
SP 920     :lines: 13
5b47ba 921
2033ee 922 .. seealso:: See also:
6a9366 923     :ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy
SP 924     <http://www.sqlalchemy.org/>`_, :ref:`making_a_console_script`,
925     :ref:`bfg_sql_wiki_tutorial`, and :ref:`Application Transactions with
926     pyramid_tm <tm:overview>`.
927
47eaa1 928
83fefb 929 Forms
PE 930 =====
47eaa1 931
6a9366 932 Developers have lots of opinions about web forms, thus there are many form
SP 933 libraries for Python. Pyramid doesn't directly bundle a form library, but
934 *Deform* is a popular choice for forms, along with its related *Colander*
935 schema system.
47eaa1 936
6a9366 937 As an example, imagine we want a form that edits a wiki page. The form should
SP 938 have two fields on it, one of them a required title and the other a rich text
939 editor for the body. With Deform we can express this as a Colander schema:
83fefb 940
d4bd29 941 .. code-block:: python
PE 942
943     class WikiPage(colander.MappingSchema):
944         title = colander.SchemaNode(colander.String())
945         body = colander.SchemaNode(
946             colander.String(),
947             widget=deform.widget.RichTextWidget()
948         )
949
6a9366 950 With this in place, we can render the HTML for a form, perhaps with form data
SP 951 from an existing page:
d4bd29 952
PE 953 .. code-block:: python
954
955     form = self.wiki_form.render()
956
957 We'd like to handle form submission, validation, and saving:
958
959 .. code-block:: python
960
961     # Get the form data that was posted
962     controls = self.request.POST.items()
963     try:
964         # Validate and either raise a validation error
965         # or return deserialized data from widgets
966         appstruct = wiki_form.validate(controls)
967     except deform.ValidationFailure as e:
968         # Bail out and render form with errors
969         return dict(title=title, page=page, form=e.render())
970
971     # Change the content and redirect to the view
972     page['title'] = appstruct['title']
973     page['body'] = appstruct['body']
974
6a9366 975 Deform and Colander provide a very flexible combination for forms, widgets,
SP 976 schemas, and validation. Recent versions of Deform also include a :ref:`retail
977 mode <deform:retail>` for gaining Deform features on custom forms.
d4bd29 978
a0ad6f 979 Deform uses attractive CSS from Twitter Bootstrap and more powerful select, checkbox, and date and time widgets.
d4bd29 980
2033ee 981 .. seealso:: See also:
a0ad6f 982     :ref:`Quick Tutorial Forms <qtut_forms>`, :ref:`Deform <deform:overview>`, and :ref:`Colander <colander:overview>`.
83fefb 983
d4bd29 984 Conclusion
PE 985 ==========
83fefb 986
ae9014 987 This *Quick Tour* covered a little about a lot. We introduced a long list
PE 988 of concepts in Pyramid, many of which are expanded on more fully in the
540fcd 989 Pyramid developer docs.