summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki2/definingmodels.rst
blob: 936abbeb6d3a224dde897abcaa48e702456fd323 (plain)
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
=========================
Defining the Domain Model
=========================

The first change we'll make to our stock pcreate-generated application will
be to define a :term:`domain model` constructor representing a wiki page.
We'll do this inside our ``models.py`` file.

The source code for this tutorial stage can be browsed at
`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/
<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/>`_.

Making Edits to ``models.py``
-----------------------------

.. note::

  There is nothing automagically special about the filename ``models.py``.  A
  project may have many models throughout its codebase in arbitrarily-named
  files.  Files implementing models often have ``model`` in their filenames
  (or they may live in a Python subpackage of your application package named
  ``models``) , but this is only by convention.

Open ``tutorial/tutorial/models.py`` file and edit it to look like the 
following:

.. literalinclude:: src/models/tutorial/models.py
   :linenos:
   :language: py
   :emphasize-lines: 20-22,25,27,29

(The highlighted lines are the ones that need to be changed.)

The first thing we've done is to do is remove the stock ``MyModel`` class
from the generated ``models.py`` file.  The ``MyModel`` class is only a
sample and we're not going to use it.

Then, we added a ``Page`` class.  Because this is a SQLAlchemy application,
this class inherits from an instance of
:class:`sqlalchemy.ext.declarative.declarative_base`.

.. literalinclude:: src/models/tutorial/models.py
   :pyobject: Page
   :linenos:
   :language: python

As you can see, our ``Page`` class has a class level attribute
``__tablename__`` which equals the string ``'pages'``.  This means that
SQLAlchemy will store our wiki data in a SQL table named ``pages``.  Our Page
class will also have class-level attributes named ``id``, ``name`` and
``data`` (all instances of :class:`sqlalchemy.Column`).  These will map to
columns in the ``pages`` table.  The ``id`` attribute will be the primary key
in the table.  The ``name`` attribute will be a text attribute, each value of
which needs to be unique within the column.  The ``data`` attribute is a text
attribute that will hold the body of each page.

Changing ``scripts/initializedb.py``
------------------------------------

We haven't looked at the details of this file yet, but within the ``scripts``
directory of your ``tutorial`` package is a file named ``initializedb.py``.  Code
in this file is executed whenever we run the ``initialize_tutorial_db`` command
(as we did in the installation step of this tutorial).

Since we've changed our model, we need to make changes to our ``initializedb.py``
script.  In particular, we'll replace our import of ``MyModel`` with one of
``Page`` and we'll change the very end of the script to create a ``Page``
rather than a ``MyModel`` and add it to our ``DBSession``.

Open ``tutorial/tutorial/scripts/initializedb.py`` and edit it to look like the 
following:

.. literalinclude:: src/models/tutorial/scripts/initializedb.py
   :linenos:
   :language: python
   :emphasize-lines: 14,34

(Only the highlighted lines need to be changed.)

Reinitializing the Database
---------------------------

Because our model has changed, in order to reinitialize the database, we need
to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made
to both the models.py file and to the initializedb.py file.  From the root of the
``tutorial`` project, directory execute the following commands.

On UNIX:

.. code-block:: text

   $ ../bin/initialize_tutorial_db development.ini

On Windows:

.. code-block:: text

   c:\pyramidtut\tutorial> ..\Scripts\initialize_tutorial_db development.ini

Success will look something like this::

  2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                PRAGMA table_info("pages")
  2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread] ()
  2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
  CREATE TABLE pages (
  	id INTEGER NOT NULL, 
  	name TEXT, 
  	data TEXT, 
  	PRIMARY KEY (id), 
  	UNIQUE (name)
  )


  2011-11-27 01:22:45,278 INFO  [sqlalchemy.engine.base.Engine][MainThread] ()
  2011-11-27 01:22:45,397 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                COMMIT
  2011-11-27 01:22:45,400 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                BEGIN (implicit)
  2011-11-27 01:22:45,401 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                INSERT INTO pages (name, data) VALUES (?, ?)
  2011-11-27 01:22:45,401 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                ('FrontPage', 'This is the front page')
  2011-11-27 01:22:45,402 INFO  [sqlalchemy.engine.base.Engine][MainThread] 
                                COMMIT

Viewing the Application in a Browser
------------------------------------

We can't.  At this point, our system is in a "non-runnable" state; we'll need
to change view-related files in the next chapter to be able to start the
application successfully.  If you try to start the application (See
:ref:`wiki2-start-the-application`), you'll wind
up with a Python traceback on your console that ends with this exception:

.. code-block:: text

   ImportError: cannot import name MyModel

This will also happen if you attempt to run the tests.