1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
.. _qtut_views:
=================================
07: Basic Web Handling With Views
=================================
Organize a views module with decorators and multiple views.
Background
==========
For the examples so far, the ``hello_world`` function is a "view". In Pyramid,
views are the primary way to accept web requests and return responses.
So far our examples place everything in one file:
- The view function
- Its registration with the configurator
- The route to map it to a URL
- The WSGI application launcher
Let's move the views out to their own ``views.py`` module and change our
startup code to scan that module, looking for decorators that set up the views.
Let's also add a second view and update our tests.
Objectives
==========
- Move views into a module that is scanned by the configurator.
- Create decorators that do declarative configuration.
Steps
=====
#. Let's begin by using the previous package as a starting point for a new
distribution, then making it active:
.. code-block:: bash
cd ..; cp -r functional_testing views; cd views
$VENV/bin/pip install -e .
#. Our ``views/tutorial/__init__.py`` gets a lot shorter:
.. literalinclude:: views/tutorial/__init__.py
:linenos:
#. Let's add a module ``views/tutorial/views.py`` that is focused on
handling requests and responses:
.. literalinclude:: views/tutorial/views.py
:linenos:
#. Update the tests to cover the two new views:
.. literalinclude:: views/tutorial/tests.py
:linenos:
#. Now run the tests:
.. code-block:: bash
$VENV/bin/pytest tutorial/tests.py -q
....
4 passed in 0.28 seconds
#. Run your Pyramid application with:
.. code-block:: bash
$VENV/bin/pserve development.ini --reload
#. Open http://localhost:6543/ and http://localhost:6543/howdy
in your browser.
Analysis
========
We added some more URLs, but we also removed the view code from the application
startup code in ``tutorial/__init__.py``. Our views, and their view
registrations (via decorators) are now in a module ``views.py``, which is
scanned via ``config.scan('.views')``.
We have two views, each leading to the other. If you start at
http://localhost:6543/, you get a response with a link to the next view. The
``hello`` view (available at the URL ``/howdy``) has a link back to the first
view.
This step also shows that the name appearing in the URL, the name of the
"route" that maps a URL to a view, and the name of the view, can all be
different. More on routes later.
Earlier we saw ``config.add_view`` as one way to configure a view. This section
introduces ``@view_config``. Pyramid's configuration supports :term:`imperative
configuration`, such as the ``config.add_view`` in the previous example. You
can also use :term:`declarative configuration`, in which a Python
:term:`python:decorator` is placed on the line above the view. Both approaches
result in the same final configuration, thus usually, it is simply a matter of
taste.
Extra credit
============
#. What does the dot in ``.views`` signify?
#. Why might ``assertIn`` be a better choice in testing the text in responses
than ``assertEqual``?
.. seealso:: :ref:`views_chapter`,
:ref:`view_config_chapter`, and
:ref:`debugging_view_configuration`
|