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