Defining the Domain Model¶
The first change we'll make to our stock cookiecutter-generated application will
be to define two resource constructors, one representing a wiki page,
and another representing the wiki as a mapping of wiki page names to page
objects. We'll do this inside our
Because we're using ZODB to represent our resource tree, each of these resource constructors represents a domain model object, so we'll call these constructors "model constructors". Both our Page and Wiki constructors will be class objects. A single instance of the "Wiki" class will serve as a container for "Page" objects, which will be instances of the "Page" class.
Delete the database¶
In the next step, we're going to remove the
MyModel Python model
class from our
models.py file. Since this class is referred to within
our persistent storage (represented on disk as a file named
we'll have strange things happen the next time we want to visit the
application in a browser. Remove the
Data.fs from the
directory before proceeding any further. It's always fine to do this as long
as you don't care about the content of the database; the database itself will
be recreated as necessary.
There is nothing special about the filename
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.
tutorial/models.py file and edit it to look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
from persistent import Persistent from persistent.mapping import PersistentMapping class Wiki(PersistentMapping): __name__ = None __parent__ = None class Page(Persistent): def __init__(self, data): self.data = data def appmaker(zodb_root): if 'app_root' not in zodb_root: app_root = Wiki() frontpage = Page('This is the front page') app_root['FrontPage'] = frontpage frontpage.__name__ = 'FrontPage' frontpage.__parent__ = app_root zodb_root['app_root'] = app_root return zodb_root['app_root']
The first thing we want to do is remove the
MyModel class from the
models.py file. The
MyModel class is only a sample and
we're not going to use it.
Then we'll add an import at the top for the
persistent.Persistent class. We'll use this for a new
Page class in a moment.
Then we'll add a
Wiki class. We want it to inherit from the
persistent.mapping.PersistentMapping class because it provides
mapping behavior, and it makes sure that our Wiki page is stored as a
"first-class" persistent object in our ZODB database.
Wiki class should have two attributes set to
__name__. If a model has a
__parent__ attribute of
None in a traversal-based Pyramid
application, it means that it's the root model. The
of the root model is also always
Then we'll add a
Page class. This class should inherit from the
persistent.Persistent class. We'll also give it an
method that accepts a single parameter named
data. This parameter will
contain the reStructuredText body representing the wiki page content.
Page objects don't have an initial
__parent__ attribute. All objects in a traversal graph must have a
__name__ and a
__parent__ attribute. We don't specify these here
__parent__ will be set by a view
function when a Page is added to our Wiki mapping.
As a last step, we want to change the
appmaker function in our
models.py file so that the root resource of our
application is a Wiki instance. We'll also slot a single page object (the
front page) into the Wiki within the
appmaker. This will provide
traversal a resource tree to work against when it attempts to
resolve URLs to resources.
View 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 Start the application), you'll wind up with a Python traceback on your console that ends with this exception:
ImportError: cannot import name MyModel
This will also happen if you attempt to run the tests.