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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
============
Basic Layout
============
The starter files generated by the ``pyramid_routesalchemy`` template
are basic, but they provide a good orientation for the high-level
patterns common to most :term:`url dispatch` -based :app:`Pyramid`
projects.
The source code for this tutorial stage can be browsed at
`http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/basiclayout/
<http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/basiclayout/>`_.
App Startup with ``__init__.py``
--------------------------------
A directory on disk can be turned into a Python :term:`package` by containing
an ``__init__.py`` file. Even if empty, this marks a directory as a Python
package. We use ``__init__.py`` both as a package marker and to contain
configuration code.
The generated ``development.ini`` file is read by ``paster`` which looks for
the application module in the ``use`` variable of the ``app:tutorial``
section. The *entry point* is defined in the Setuptools configuration of this
module, specifically in the ``setup.py`` file. For this tutorial, the *entry
point* is defined as ``tutorial:main`` and points to a function named ``main``.
First we need some imports to support later code:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:end-before: main
:linenos:
:language: py
Next we define the main function and create a SQLAlchemy database
engine from the ``sqlalchemy.`` prefixed settings in the ``development.ini`
`file's ``[app:tutorial]`` section. This will be a URI (something like
``sqlite://``):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 6-9
:linenos:
:language: py
We then initialize our SQL database using SQLAlchemy, passing
it the engine:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 10
:language: py
The next step is to construct a :term:`Configurator`:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 11
:language: py
``settings`` is passed as a keyword argument with the dictionary values
passed by PasteDeploy as the ``settings`` argument. This will be a
dictionary of settings parsed by PasteDeploy, which contains
deployment-related values such as ``reload_templates``,
``db_string``, etc.
We now can call :meth:`pyramid.config.Configurator.add_static_view` with the
arguments ``static`` (the name), and ``tutorial:static`` (the path):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 12
:language: py
This registers a static resource view which will match any URL that starts with
``/static/``. This will serve up static resources for us from within the
``static`` directory of our ``tutorial`` package, in this case,
via ``http://localhost:6543/static/`` and below. With this declaration,
we're saying that any URL that starts with ``/static`` should go to the
static view; any remainder of its path (e.g. the ``/foo`` in
``/static/foo``) will be used to compose a path to a static file resource,
such as a CSS file.
Using the configurator we can also register a :term:`route configuration`
via the :meth:`pyramid.config.Configurator.add_route` method that will be
used when the URL is ``/``:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 13-14
:language: py
Since this route has a ``pattern`` equalling
``/`` it is the "default" route. The argument named ``view`` with the
value ``tutorial.views.my_view`` is the dotted name to a *function* we
write (generated by the ``pyramid_routesalchemy`` template) that is given
a ``request`` object and which returns a response or a dictionary.
You will use :meth:`pyramid.config.Configurator.add_route` statements
in a :term:`URL dispatch` based application to map URLs to code. This
route also names a ``view_renderer``, which is a template which lives in
the ``templates`` subdirectory of the package. When the
``tutorial.views.my_view`` view returns a dictionary, a :term:`renderer`
will use this template to create a response.
Fimnally, we use the :meth:`pyramid.config.Configurator.make_wsgi_app`
method to return a :term:`WSGI` application:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 15
:language: py
Our final __init__.py file will look like this:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:linenos:
:language: py
Content Models with ``models.py``
---------------------------------
In a SQLAlchemy-based application, a *model* object is an object
composed by querying the SQL database which backs an application.
SQLAlchemy is an "object relational mapper" (an ORM). The
``models.py`` file is where the ``pyramid_routesalchemy`` Paster
template put the classes that implement our models.
Let's take a look. First, we need some imports to support later code.
.. literalinclude:: src/basiclayout/tutorial/models.py
:end-before: DBSession
:linenos:
:language: py
Next we set up a SQLAlchemy "DBSession" object:
.. literalinclude:: src/basiclayout/tutorial/models.py
:lines: 15-16
:linenos:
:language: py
We also need to create a declarative ``Base`` object to use as a
base class for our model:
.. literalinclude:: src/basiclayout/tutorial/models.py
:lines: 17
:language: py
To give a simple example of a model class, we define one named ``MyModel``:
.. literalinclude:: src/basiclayout/tutorial/models.py
:pyobject: MyModel
:linenos:
:language: py
Our sample model has an ``__init__`` that takes a two arguments
(``name``, and ``value``).
It stores these values as ``self.name`` and ``self.value`` within
the ``__init__`` function itself. The ``MyModel`` class also has a
``__tablename__`` attribute. This informs SQLAlchemy which table
to use to store the data representing instances of this class.
Next we define a function named ``populate`` which adds a single
model instance into our SQL storage and commits a transaction:
.. literalinclude:: src/basiclayout/tutorial/models.py
:pyobject: populate
:linenos:
:language: py
The function doesn't do a lot in this case, but it's there to illustrate
how an application requiring many objects to be set up could work.
Lastly we have a function named ``initialize_sql`` which receives a SQL
database engine and binds it to our SQLAlchemy DBSession object. It also
calls the ``populate`` function, to do initial database population. This
is the initialization function that is called from __init__.py above.
.. literalinclude:: src/basiclayout/tutorial/models.py
:pyobject: initialize_sql
:linenos:
:language: py
Here is the complete source for ``models.py``:
.. literalinclude:: src/basiclayout/tutorial/models.py
:linenos:
:language: py
|