Following is a quick overview of the design of our wiki application to help us understand the changes that we will be making as we work through the tutorial.


We choose to use reStructuredText markup in the wiki text. Translation from reStructuredText to HTML is provided by the widely used docutils Python module. We will add this module to the dependency list in the project's file.


We'll be using an SQLite database to hold our wiki data, and we'll be using SQLAlchemy to access the data in this database. We will also use Alembic for database migrations, including initialization of the SQLite database.

Within the database, we will define two tables:

  • The users table which will store the id, name, password_hash and role of each wiki user.
  • The pages table, whose elements will store the wiki pages. There are four columns: id, name, data and creator_id.

There is a one-to-many relationship between users and pages tracking the user who created each wiki page defined by the creator_id column on the pages table.

URLs like /PageName will try to find an element in the pages table that has a corresponding name.

To add a page to the wiki, a new row is created and the text is stored in data.

A page named FrontPage containing the text "This is the front page" will be created when the storage is initialized, and will be used as the wiki home page.

Wiki Views

There will be three views to handle the normal operations of adding, editing, and viewing wiki pages, plus one view for the wiki front page. Two templates will be used, one for viewing, and one for both adding and editing wiki pages.

As of version 1.5 Pyramid no longer ships with templating systems. In this tutorial, we will use Jinja2. Jinja2 is a modern and designer-friendly templating language for Python, modeled after Django's templates.


We'll eventually be adding security to our application. To do this, we'll be using a very simple role-based security model. We'll assign a single role category to each user in our system.

An authenticated user who can view content and create new pages. A basic user may also edit the pages they have created but not pages created by other users.
An authenticated user who can create and edit any content in the system.

In order to accomplish this we'll need to define an authentication policy which can identify users by their userid and role. Then we'll need to define a page resource which contains the appropriate ACL:

Action Principal Permission
Allow Everyone view
Allow group:basic create
Allow group:editors edit
Allow <creator of page> edit

Permission declarations will be added to the views to assert the security policies as each request is handled.

On the security side of the application there are two additional views for handling login and logout as well as two exception views for handling invalid access attempts and unhandled URLs.


The URL, actions, template, and permission associated to each view are listed in the following table:

URL Action View Template Permission
/ Redirect to /FrontPage view_wiki    
/PageName Display existing page [2] view_page [1] view.jinja2 view

Display edit form with existing content.

If the form was submitted, redirect to /PageName

edit_page edit.jinja2 edit

Create the page PageName in storage, display the edit form without content.

If the form was submitted, redirect to /PageName

add_page edit.jinja2 create

Display login form, Forbidden [3]

If the form was submitted, authenticate.

  • If authentication succeeds, redirect to the page from which we came.
  • If authentication fails, display login form with "login failed" message.
login login.jinja2  
/logout Redirect to /FrontPage logout    
[1]This is the default view for a Page context when there is no view name.
[2]Pyramid will return a default 404 Not Found page if the page PageName does not exist yet.
[3]pyramid.exceptions.Forbidden is reached when a user tries to invoke a view that is not authorized by the authorization policy.