Michael Merickel
2018-10-16 8eed333343e4e9e7f11f3aee67299030d6bf2783
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
e6581f 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
9ce94f 20 Quick Tour, it means `Python <https://www.python.org/downloads/>`_, :mod:`python:venv` (or `virtualenv for
SP 21 Python 2.7 <https://virtualenv.pypa.io/en/stable/>`_),
315e46 22 `pip <https://pypi.org/project/pip/>`_, and `Setuptools
9ce94f 23 <https://pypi.org/project/setuptools/>`_.
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
1c44d2 29 As an example, for Python 3 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
b730ae 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
5af300 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
4b84f6 90 #. *Lines 6-7*. Implement the view code that generates the :term:`response`.
SP 91
257ac0 92 #. *Line 10*. ``if __name__ == '__main__':`` is Python's way of saying "Start
SP 93    here when running from the command line".
47eaa1 94
2d7b91 95 #. *Lines 11-13*. Use Pyramid's :term:`configurator` in a :term:`context manager` to connect :term:`view`
257ac0 96    code to a particular URL :term:`route`.
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
2cbda9 136     URL http://localhost:6543/?name=alice with name: alice
d559af 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
2cbda9 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
2cbda9 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
6b6d0e 501 To ease the process of getting started, the Pylons Project provides a :term:`cookiecutter` that generates sample Pyramid projects from project templates. This cookiecutter 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
2cbda9 507     $VENV/bin/pip install cookiecutter
47eaa1 508
28e688 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
0080e9 513     $VENV/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.10-branch
47eaa1 514
a0ebd7 515 If prompted for the first item, accept the default ``yes`` by hitting return.
SP 516
2cd381 517 .. code-block:: text
SP 518
28e688 519     You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
2cd381 520     Is it okay to delete and re-clone it? [yes]: yes
SP 521     project_name [Pyramid Scaffold]: hello_world
6ff6fa 522     repo_name [hello_world]: hello_world
2cd381 523     Select template_language:
SP 524     1 - jinja2
525     2 - chameleon
6204d8 526     3 - mako
6b6d0e 527     Choose from 1, 2, 3 [1]: 1
SM 528     Select backend:
529     1 - none
530     2 - sqlalchemy
531     3 - zodb
6204d8 532     Choose from 1, 2, 3 [1]: 1
a0ebd7 533
b488f7 534 We then run through the following commands.
47eaa1 535
PE 536 .. code-block:: bash
537
a0ebd7 538     # Change directory into your newly created project.
2cbda9 539     cd hello_world
a0ebd7 540     # Create a new virtual environment...
2cbda9 541     python3 -m venv env
a0ebd7 542     # ...where we upgrade packaging tools...
2cbda9 543     env/bin/pip install --upgrade pip setuptools
a0ebd7 544     # ...and into which we install our project and its testing requirements.
2cbda9 545     env/bin/pip install -e ".[testing]"
2cd1ea 546     # Reset our environment variable for a new virtual environment.
2cbda9 547     export VENV=~/hello_world/env
47eaa1 548
5cf8c3 549 We are moving in the direction of a full-featured Pyramid project, with a
SP 550 proper setup for Python standards (packaging) and Pyramid configuration. This
551 includes a new way of running your application:
47eaa1 552
PE 553 .. code-block:: bash
554
2cbda9 555     $VENV/bin/pserve development.ini
47eaa1 556
PE 557 Let's look at ``pserve`` and configuration in more depth.
5b47ba 558
2033ee 559 .. seealso:: See also:
49cd00 560     :ref:`Quick Tutorial Cookiecutters <qtut_cookiecutters>`,
b731b5 561     :ref:`project_narr`, and
d5b5d0 562     :doc:`../narr/cookiecutters`
47eaa1 563
1273d0 564 Application running with ``pserve``
47eaa1 565 ===================================
PE 566
2cd1ea 567 Prior to the cookiecutter, our project mixed a number of operational details into our
5cf8c3 568 code. Why should my main code care which HTTP server I want and what port
SP 569 number to run on?
d4bd29 570
5cf8c3 571 ``pserve`` is Pyramid's application runner, separating operational details from
SP 572 your code. When you install Pyramid, a small command program called ``pserve``
573 is written to your ``bin`` directory. This program is an executable Python
574 module. It's very small, getting most of its brains via import.
47eaa1 575
5cf8c3 576 You can run ``pserve`` with ``--help`` to see some of its options. Doing so
SP 577 reveals that you can ask ``pserve`` to watch your development files and reload
578 the server when they change:
47eaa1 579
PE 580 .. code-block:: bash
581
2cbda9 582     $VENV/bin/pserve development.ini --reload
47eaa1 583
5cf8c3 584 The ``pserve`` command has a number of other options and operations. Most of
SP 585 the work, though, comes from your project's wiring, as expressed in the
586 configuration file you supply to ``pserve``. Let's take a look at this
587 configuration file.
49d634 588
2033ee 589 .. seealso:: See also:
b731b5 590     :ref:`what_is_this_pserve_thing`
47eaa1 591
1273d0 592 Configuration with ``.ini`` files
47eaa1 593 =================================
PE 594
5cf8c3 595 Earlier in *Quick Tour* we first met Pyramid's configuration system. At that
SP 596 point we did all configuration in Python code. For example, the port number
2cd1ea 597 chosen for our HTTP server was right there in Python code. Our cookiecutter has
5cf8c3 598 moved this decision and more into the ``development.ini`` file:
d4bd29 599
ae9014 600 .. literalinclude:: quick_tour/package/development.ini
d4bd29 601     :language: ini
47eaa1 602
5cf8c3 603 Let's take a quick high-level look. First the ``.ini`` file is divided into
SP 604 sections:
47eaa1 605
5cf8c3 606 - ``[app:main]`` configures our WSGI app
47eaa1 607
PE 608 - ``[server:main]`` holds our WSGI server settings
609
610 - Various sections afterwards configure our Python logging system
611
d4bd29 612 We have a few decisions made for us in this configuration:
47eaa1 613
1273d0 614 #. *WSGI app:* What package has our WSGI application in it?
5cf8c3 615    ``use = egg:hello_world`` in the app section tells the configuration what
SP 616    application to load.
47eaa1 617
1273d0 618 #. *Easier development by automatic template reloading:* In development mode,
SP 619    you shouldn't have to restart the server when editing a Jinja2 template.
5cf8c3 620    ``pyramid.reload_templates = true`` sets this policy, which might be
SP 621    different in production.
47eaa1 622
785776 623 #. *Choice of web server:* ``use = egg:waitress#main`` tells ``pserve`` to
SP 624    use the ``waitress`` server.
625
6d120e 626 #. *Interfaces:* ``listen = localhost:6543`` tells ``waitress`` to listen on all interfaces on port 6543 for both IPv4 and IPv6.
785776 627
d5b5d0 628 Additionally the ``development.ini`` generated by this cookiecutter wired up
5cf8c3 629 Python's standard logging. We'll now see in the console, for example, a log on
SP 630 every request that comes in, as well as traceback information.
47eaa1 631
2033ee 632 .. seealso:: See also:
b731b5 633     :ref:`Quick Tutorial Application Configuration <qtut_ini>`,
PE 634     :ref:`environment_chapter` and
635     :doc:`../narr/paste`
49d634 636
5b47ba 637
1273d0 638 Easier development with ``debugtoolbar``
47eaa1 639 ========================================
PE 640
58febc 641 As we introduce the basics, we also want to show how to be productive in
5cf8c3 642 development and debugging. For example, we just discussed template reloading
SP 643 and earlier we showed ``--reload`` for application reloading.
47eaa1 644
5cf8c3 645 ``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes several tools
SP 646 available in your browser. Adding it to your project illustrates several points
647 about configuration.
47eaa1 648
28e688 649 Our cookiecutter ``pyramid-cookiecutter-starter`` already configured our package to include the
5cf8c3 650 add-on ``pyramid_debugtoolbar`` in its ``setup.py``:
47eaa1 651
ae9014 652 .. literalinclude:: quick_tour/package/setup.py
5cf8c3 653     :language: python
af1e32 654     :lineno-match:
65a6d3 655     :lines: 11-17
SP 656     :emphasize-lines: 5
47eaa1 657
5cf8c3 658 It was installed when you previously ran:
47eaa1 659
PE 660 .. code-block:: bash
661
2cbda9 662     $VENV/bin/pip install -e ".[testing]"
47eaa1 663
5cf8c3 664 The ``pyramid_debugtoolbar`` package is a Pyramid add-on, which means we need
65a6d3 665 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 666
ae9014 667 .. literalinclude:: quick_tour/package/development.ini
d4bd29 668     :language: ini
af1e32 669     :lineno-match:
SP 670     :lines: 14-15
47eaa1 671
5cf8c3 672 You'll now see a Pyramid logo on the right side of your browser window, which
SP 673 when clicked opens a new window that provides introspective access to debugging
674 information. Even better, if your web application generates an error, you will
675 see a nice traceback on the screen. When you want to disable this toolbar,
676 there's no need to change code: you can remove it from ``pyramid.includes`` in
677 the relevant ``.ini`` configuration file.
5b47ba 678
2033ee 679 .. seealso:: See also:
5cf8c3 680     :ref:`Quick Tutorial pyramid_debugtoolbar <qtut_debugtoolbar>` and
b731b5 681     :ref:`pyramid_debugtoolbar <toolbar:overview>`
47eaa1 682
d363b4 683 Unit tests and ``pytest``
9c39f6 684 =========================
47eaa1 685
5cf8c3 686 Yikes! We got this far and we haven't yet discussed tests. This is particularly
SP 687 egregious, as Pyramid has had a deep commitment to full test coverage since
688 before its release.
47eaa1 689
28e688 690 Our ``pyramid-cookiecutter-starter`` cookiecutter generated a ``tests.py`` module with
948344 691 one unit test and one functional test in it. It also configured ``setup.py`` with test requirements:
d363b4 692 ``pytest`` as the test runner, ``WebTest`` for running view tests, and the
65a6d3 693 ``pytest-cov`` tool which yells at us for code that isn't tested:
47eaa1 694
948344 695 .. literalinclude:: quick_tour/package/setup.py
SP 696     :language: python
697     :lineno-match:
65a6d3 698     :lines: 19-23
47eaa1 699
948344 700 .. literalinclude:: quick_tour/package/setup.py
SP 701     :language: python
702     :lineno-match:
65a6d3 703     :lines: 43-45
47eaa1 704
948344 705 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 706
PE 707 .. code-block:: bash
708
d363b4 709     $VENV/bin/pytest --cov --cov-report=term-missing
47eaa1 710
ebbe68 711 This yields the following output.
47eaa1 712
ebbe68 713 .. code-block:: text
SP 714
715     =========================== test session starts ===========================
948344 716     platform darwin -- Python 3.6.0, pytest-3.0.5, py-1.4.32, pluggy-0.4.0
SP 717     rootdir: /Users/stevepiercy/hello_world, inifile: pytest.ini
718     plugins: cov-2.4.0
719     collected 2 items
ebbe68 720
948344 721     hello_world/tests.py ..
SP 722
c8a5e0 723     ------------- coverage: platform darwin, python 3.6.0-final-0 -------------
948344 724     Name                                      Stmts   Miss  Cover   Missing
SP 725     -----------------------------------------------------------------------
726     hello_world/__init__.py                       8      0   100%
727     hello_world/views.py                          3      0   100%
728     -----------------------------------------------------------------------
729     TOTAL                                        11      0   100%
ebbe68 730
SP 731
948344 732     ========================= 2 passed in 1.37 seconds =========================
SP 733
734 Our tests passed, and its coverage is complete. What did our test look like?
47eaa1 735
ae9014 736 .. literalinclude:: quick_tour/package/hello_world/tests.py
da42d5 737     :language: python
5cf8c3 738     :linenos:
47eaa1 739
5cf8c3 740 Pyramid supplies helpers for test writing, which we use in the test setup and
948344 741 teardown. Our first test imports the view, makes a dummy request, and sees if the
SP 742 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 743
2033ee 744 .. seealso:: See also:
5cf8c3 745     :ref:`Quick Tutorial Unit Testing <qtut_unit_testing>`, :ref:`Quick
SP 746     Tutorial Functional Testing <qtut_functional_testing>`, and
b731b5 747     :ref:`testing_chapter`
5b47ba 748
83fefb 749 Logging
PE 750 =======
751
5cf8c3 752 It's important to know what is going on inside our web application. In
SP 753 development we might need to collect some output. In production we might need
754 to detect situations when other people use the site. We need *logging*.
83fefb 755
c87565 756 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 757 logging for you to some reasonable defaults. You then see messages sent by
SP 758 Pyramid (for example, when a new request comes in).
83fefb 759
5cf8c3 760 Maybe you would like to log messages in your code? In your Python module,
c87565 761 import and set up the logging in your ``views.py``:
83fefb 762
8f30e8 763 .. literalinclude:: quick_tour/logging/hello_world/views/default.py
5cf8c3 764     :language: python
c87565 765     :lineno-match:
5cf8c3 766     :lines: 3-4
83fefb 767
PE 768 You can now, in your code, log messages:
769
8f30e8 770 .. literalinclude:: quick_tour/logging/hello_world/views/default.py
5cf8c3 771     :language: python
c87565 772     :lineno-match:
SP 773     :lines: 7-8
5cf8c3 774     :emphasize-lines: 2
83fefb 775
c87565 776 This will log ``Some Message`` at a ``DEBUG`` log level to the
5cf8c3 777 application-configured logger in your ``development.ini``. What controls that?
SP 778 These emphasized sections in the configuration file:
83fefb 779
c87565 780 .. literalinclude:: quick_tour/logging/development.ini
d4bd29 781     :language: ini
c87565 782     :lineno-match:
SP 783     :lines: 34-50
5cf8c3 784     :emphasize-lines: 1-2,14-17
83fefb 785
5cf8c3 786 Our application, a package named ``hello_world``, is set up as a logger and
SP 787 configured to log messages at a ``DEBUG`` or higher level. When you visit
556258 788 http://localhost:6543, your console will now show:
SP 789
790 .. code-block:: text
d4bd29 791
c87565 792     2016-12-25 03:03:57,059 DEBUG [hello_world.views:8][waitress] Some Message
5b47ba 793
2033ee 794 .. seealso:: See also:
5cf8c3 795     :ref:`Quick Tutorial Logging <qtut_logging>` and :ref:`logging_chapter`.
83fefb 796
PE 797 Sessions
798 ========
799
5cf8c3 800 When people use your web application, they frequently perform a task that
SP 801 requires semi-permanent data to be saved. For example, a shopping cart. This is
802 called a :term:`session`.
83fefb 803
5cf8c3 804 Pyramid has basic built-in support for sessions. Third party packages such as
SP 805 ``pyramid_redis_sessions`` provide richer session support. Or you can create
806 your own custom sessioning engine. Let's take a look at the :doc:`built-in
807 sessioning support <../narr/sessions>`. In our ``__init__.py`` we first import
808 the kind of sessioning we want:
83fefb 809
64009a 810 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 811     :language: python
64009a 812     :lineno-match:
SP 813     :lines: 1-2
5cf8c3 814     :emphasize-lines: 2
83fefb 815
d4bd29 816 .. warning::
83fefb 817
5cf8c3 818     As noted in the session docs, this example implementation is not intended
SP 819     for use in settings with security implications.
83fefb 820
d4bd29 821 Now make a "factory" and pass it to the :term:`configurator`'s
PE 822 ``session_factory`` argument:
83fefb 823
64009a 824 .. literalinclude:: quick_tour/sessions/hello_world/__init__.py
5cf8c3 825     :language: python
64009a 826     :lineno-match:
8f30e8 827     :lines: 9-12
64009a 828     :emphasize-lines: 2-3
83fefb 829
5cf8c3 830 Pyramid's :term:`request` object now has a ``session`` attribute that we can
SP 831 use in our view code in ``views.py``:
83fefb 832
8f30e8 833 .. literalinclude:: quick_tour/sessions/hello_world/views/default.py
5cf8c3 834     :language: python
64009a 835     :lineno-match:
SP 836     :lines: 7-
5cf8c3 837     :emphasize-lines: 3-7
83fefb 838
64009a 839 We need to update our Jinja2 template ``templates/mytemplate.jinja2`` to show counter increment in the session:
d4bd29 840
64009a 841 .. literalinclude:: quick_tour/sessions/hello_world/templates/mytemplate.jinja2
d4bd29 842     :language: jinja
64009a 843     :lineno-match:
SP 844     :lines: 4-8
845     :emphasize-lines: 4
d4bd29 846
2033ee 847 .. seealso:: See also:
5cf8c3 848     :ref:`Quick Tutorial Sessions <qtut_sessions>`, :ref:`sessions_chapter`,
SP 849     :ref:`flash_messages`, :ref:`session_module`, and
850     :term:`pyramid_redis_sessions`.
83fefb 851
PE 852
853 Databases
854 =========
855
6a9366 856 Web applications mean data. Data means databases. Frequently SQL databases. SQL
SP 857 databases frequently mean an "ORM" (object-relational mapper.) In Python, ORM
858 usually leads to the mega-quality *SQLAlchemy*, a Python package that greatly
859 eases working with databases.
83fefb 860
b488f7 861 Pyramid and SQLAlchemy are great friends. That friendship includes a cookiecutter!
83fefb 862
PE 863 .. code-block:: bash
864
2cbda9 865     cd ~
0080e9 866     env/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.10-branch
b488f7 867
SP 868 If prompted for the first item, accept the default ``yes`` by hitting return.
869
2cd381 870 .. code-block:: text
SP 871
28e688 872     You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
2cd381 873     Is it okay to delete and re-clone it? [yes]: yes
SP 874     project_name [Pyramid Scaffold]: sqla_demo
6ff6fa 875     repo_name [sqla_demo]: sqla_demo
6b6d0e 876     Select template_language:
SM 877     1 - jinja2
878     2 - chameleon
879     3 - mako
880     Choose from 1, 2, 3 [1]: 1
881     Select backend:
882     1 - none
883     2 - sqlalchemy
884     3 - zodb
885     Choose from 1, 2, 3 [1]: 2
b488f7 886
SP 887 We then run through the following commands as before.
888
889 .. code-block:: bash
890
891     # Change directory into your newly created project.
2cbda9 892     cd sqla_demo
b488f7 893     # Create a new virtual environment...
2cbda9 894     python3 -m venv env
b488f7 895     # ...where we upgrade packaging tools...
2cbda9 896     env/bin/pip install --upgrade pip setuptools
b488f7 897     # ...and into which we install our project and its testing requirements.
2cbda9 898     env/bin/pip install -e ".[testing]"
b488f7 899     # Reset our environment variable for a new virtual environment.
2cbda9 900     export VENV=~/sqla_demo/env
83fefb 901
6a9366 902 We now have a working sample SQLAlchemy application with all dependencies
SP 903 installed. The sample project provides a console script to initialize a SQLite
904 database with tables. Let's run it, then start the application:
83fefb 905
PE 906 .. code-block:: bash
907
2cbda9 908     $VENV/bin/initialize_sqla_demo_db development.ini
SP 909     $VENV/bin/pserve development.ini
83fefb 910
6a9366 911 The ORM eases the mapping of database structures into a programming language.
d5b5d0 912 SQLAlchemy uses "models" for this mapping. The cookiecutter generated a sample
6a9366 913 model:
83fefb 914
414b67 915 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py
da42d5 916     :language: python
b488f7 917     :lineno-match:
SP 918     :pyobject: MyModel
83fefb 919
6a9366 920 View code, which mediates the logic between web requests and the rest of the
SP 921 system, can then easily get at the data thanks to SQLAlchemy:
83fefb 922
3eb1c3 923 .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py
da42d5 924     :language: python
b488f7 925     :lineno-match:
SP 926     :lines: 13
5b47ba 927
2033ee 928 .. seealso:: See also:
6a9366 929     :ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy
SP 930     <http://www.sqlalchemy.org/>`_, :ref:`making_a_console_script`,
931     :ref:`bfg_sql_wiki_tutorial`, and :ref:`Application Transactions with
932     pyramid_tm <tm:overview>`.
933
47eaa1 934
83fefb 935 Forms
PE 936 =====
47eaa1 937
6a9366 938 Developers have lots of opinions about web forms, thus there are many form
SP 939 libraries for Python. Pyramid doesn't directly bundle a form library, but
940 *Deform* is a popular choice for forms, along with its related *Colander*
941 schema system.
47eaa1 942
6a9366 943 As an example, imagine we want a form that edits a wiki page. The form should
SP 944 have two fields on it, one of them a required title and the other a rich text
945 editor for the body. With Deform we can express this as a Colander schema:
83fefb 946
d4bd29 947 .. code-block:: python
PE 948
949     class WikiPage(colander.MappingSchema):
950         title = colander.SchemaNode(colander.String())
951         body = colander.SchemaNode(
952             colander.String(),
953             widget=deform.widget.RichTextWidget()
954         )
955
6a9366 956 With this in place, we can render the HTML for a form, perhaps with form data
SP 957 from an existing page:
d4bd29 958
PE 959 .. code-block:: python
960
961     form = self.wiki_form.render()
962
963 We'd like to handle form submission, validation, and saving:
964
965 .. code-block:: python
966
967     # Get the form data that was posted
968     controls = self.request.POST.items()
969     try:
970         # Validate and either raise a validation error
971         # or return deserialized data from widgets
972         appstruct = wiki_form.validate(controls)
973     except deform.ValidationFailure as e:
974         # Bail out and render form with errors
975         return dict(title=title, page=page, form=e.render())
976
977     # Change the content and redirect to the view
978     page['title'] = appstruct['title']
979     page['body'] = appstruct['body']
980
6a9366 981 Deform and Colander provide a very flexible combination for forms, widgets,
SP 982 schemas, and validation. Recent versions of Deform also include a :ref:`retail
983 mode <deform:retail>` for gaining Deform features on custom forms.
d4bd29 984
a0ad6f 985 Deform uses attractive CSS from Twitter Bootstrap and more powerful select, checkbox, and date and time widgets.
d4bd29 986
2033ee 987 .. seealso:: See also:
a0ad6f 988     :ref:`Quick Tutorial Forms <qtut_forms>`, :ref:`Deform <deform:overview>`, and :ref:`Colander <colander:overview>`.
83fefb 989
d4bd29 990 Conclusion
PE 991 ==========
83fefb 992
ae9014 993 This *Quick Tour* covered a little about a lot. We introduced a long list
PE 994 of concepts in Pyramid, many of which are expanded on more fully in the
540fcd 995 Pyramid developer docs.