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