36
TCC Web framework implementation: Pylons 1.0 John W. Shipman 2010-12-16 12:43 Abstract Design and implementation of a general Web site for the New Mexico Tech Computer Center. This publication is available in Web form 1 and also as a PDF document 2 . Please forward any comments to [email protected]. Table of Contents 1. Overview of Pylons customization ............................................................................................ 2 2. Project methodology ................................................................................................................ 3 3. Directory layout ....................................................................................................................... 3 4. Testing .................................................................................................................................... 4 4.1. Activating and deactivating the virtual environment ........................................................ 5 4.2. Testing in the development environment ......................................................................... 5 5. Files in the base directory ......................................................................................................... 6 5.1. The stockdev.ini file ................................................................................................. 6 5.2. The stocktest.ini file .............................................................................................. 8 6. Files in the project directory ...................................................................................................... 9 6.1. __init__.py ............................................................................................................... 9 6.2. websetup.py .............................................................................................................. 9 7. Configuration files: config/ .................................................................................................... 9 7.1. config/__init__.py ................................................................................................. 9 7.2. config/deployment.ini_tmpl ............................................................................... 10 7.3. config/environment.py ......................................................................................... 11 7.4. config/middleware.py ........................................................................................... 12 7.5. config/routing.py ................................................................................................. 14 8. Controllers ............................................................................................................................. 15 8.1. How to add a new controller ......................................................................................... 15 8.2. controllers/__init__.py ..................................................................................... 16 8.3. controllers/acct.py: Authenticated account operations ......................................... 16 8.3.1. The acct/index action .................................................................................... 17 8.3.2. The acct/newpass action: Change your password ............................................ 17 8.4. controllers/error.py ........................................................................................... 18 8.5. controllers/info.py: Public information controller ................................................ 19 8.5.1. The info/index action .................................................................................... 19 8.5.2. The info/motd action ...................................................................................... 19 1 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/ 2 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/site.pdf 1 TCC Web framework: Pylons 1.0 New Mexico Tech Computer Center

TCC Web framework implementation: Pylons 1infohost.nmt.edu/tcc/projects/pylons/newroot/NMTCC/site.pdf · Computer Center (TCC). For the external specification of this project, see

  • Upload
    lehanh

  • View
    223

  • Download
    1

Embed Size (px)

Citation preview

TCC Web frameworkimplementation: Pylons1.0

John W. Shipman2010-12-16 12:43

Abstract

Design and implementation of a general Web site for the New Mexico Tech Computer Center.

This publication is available in Web form1 and also as a PDF document2. Please forward anycomments to [email protected].

Table of Contents1. Overview of Pylons customization ............................................................................................ 22. Project methodology ................................................................................................................ 33. Directory layout ....................................................................................................................... 34. Testing .................................................................................................................................... 4

4.1. Activating and deactivating the virtual environment ........................................................ 54.2. Testing in the development environment ......................................................................... 5

5. Files in the base directory ......................................................................................................... 65.1. The stockdev.ini file ................................................................................................. 65.2. The stocktest.ini file .............................................................................................. 8

6. Files in the project directory ...................................................................................................... 96.1. __init__.py ............................................................................................................... 96.2. websetup.py .............................................................................................................. 9

7. Configuration files: config/ .................................................................................................... 97.1. config/__init__.py ................................................................................................. 97.2. config/deployment.ini_tmpl ............................................................................... 107.3. config/environment.py ......................................................................................... 117.4. config/middleware.py ........................................................................................... 127.5. config/routing.py ................................................................................................. 14

8. Controllers ............................................................................................................................. 158.1. How to add a new controller ......................................................................................... 158.2. controllers/__init__.py ..................................................................................... 168.3. controllers/acct.py: Authenticated account operations ......................................... 16

8.3.1. The acct/index action .................................................................................... 178.3.2. The acct/newpass action: Change your password ............................................ 17

8.4. controllers/error.py ........................................................................................... 188.5. controllers/info.py: Public information controller ................................................ 19

8.5.1. The info/index action .................................................................................... 198.5.2. The info/motd action ...................................................................................... 19

1 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/2 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/site.pdf

1TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

About this document
This document has been generated with RenderX XEP. Visit http://www.renderx.com/ to learn more about RenderX family of software solutions for digital typography.

9. The lib/ directory ................................................................................................................ 209.1. lib/__init__.py ..................................................................................................... 209.2. lib/app_globals.py ............................................................................................... 209.3. lib/base.py ............................................................................................................. 209.4. lib/helpers.py ....................................................................................................... 21

9.4.1. Imports for lib/helpers.py ........................................................................... 219.4.2. The LocalTimeZone class ................................................................................ 229.4.3. h.motd(): Message of the day .......................................................................... 239.4.4. h.timeNow(): Date and time for humans .......................................................... 24

10. The model/ directory ........................................................................................................... 2410.1. model/__init__.py ............................................................................................... 2410.2. model/meta.py ....................................................................................................... 25

11. The public/ directory ......................................................................................................... 2511.1. public/tccstyle.css: The local stylesheet ............................................................. 28

12. The templates/ directory ................................................................................................... 2812.1. How to add a new template ......................................................................................... 2912.2. templates/__init__.py ....................................................................................... 2912.3. templates/base.html: The top-level site template ................................................... 2912.4. templates/page.html: Sample view template ......................................................... 3112.5. The acct.html template ........................................................................................... 3112.6. The login.html view ............................................................................................... 3212.7. The logout.html view ............................................................................................. 3212.8. The motd.html view ................................................................................................. 3212.9. The newpass.html view: Change your password ....................................................... 32

13. The tests/ directory ........................................................................................................... 3313.1. tests/__init__.py ............................................................................................... 3313.2. tests/functional/__init__.py ......................................................................... 3313.3. tests/test_models.py ......................................................................................... 33

14. Notes on package installs ....................................................................................................... 3414.1. Installing and setting up virtualenv.py ................................................................... 3414.2. Pylon and other package installs .................................................................................. 3414.3. Installing YUI ............................................................................................................. 35

1. Overview of Pylons customizationThis document contains the actual code for the general Web framework for the New Mexico TechComputer Center (TCC). For the external specification of this project, see TCC unified Web framework3.

The code is presented in lightweight literate programming4 form, using the Cleanroom software devel-opment methodology5.

The indispensable resource for this project is the Pylons book:

Gardner, James. The definitive guide to Pylons. Apress, 2009, ISBN 978-1-59059-934-1.

The fundamental organizing principle of Pylons is the Model-View-Controller (MVC) architecture.

• When a user requests a page with a given URL, Pylons routes it to a controller that decides what doto with it. Routing is configured in Section 7.5, “config/routing.py” (p. 14).

3 http://www.nmt.edu/tcc/projects/webframe4 http://www.nmt.edu/~shipman/soft/litprog/5 http://www.nmt.edu/~shipman/soft/clean/

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.02

Each controller has one or more actions. For example, the info controller handles requests for generalinformation. Its motd action displays the Message Of The Day; its hours action displays the schedule.

• A view, or view template as it is called in Pylons, is a pattern that structures the display of a page thatfulfills some user request. Styling of these templates is via CSS.

• The model is the part of Pylons that persistently stores information. It is built on top of the SQLAlchemydatabase adapter.

Whenever a transaction requires some change to the model, the controller first transmits the new in-formation to the model, then activates the view, which can retrieve information from the model anddisplay it on the generated Web page.

Hence, the job of customization a Pylons site mainly involves these tasks:

• Creating and maintaining a database schema for the model.• Building a hierarchy of controllers and actions.• Build an associated set of view templates, and maintain the CSS stylesheet to style them.

2. Project methodologyThis project is managed with the Git6 source code control system.

The paster create command creates a number of files at project creation time. Some of those fileshave been moved into this document to present them in literate style. The git status commandenumerates all files that have been changed since the last commit; each such file must be disposed ofas follows:

• Many of the created files were initially enumerated in the .gitignore file until there is some needto change them.

• When a file is first changed, its name remains in the .gitignore file, but it must then be movedinto this document so that the make code command will re-create it from the documented source.

3. Directory layoutThis project's files live in a complex structure. Here is a diagram of the upper levels of this structure.

6 http://git-scm.com/documentation

3TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

http://www.nmt.edu/

/u/www/docs/ tcc/ projects/ pylons/ newroot/ NMTCC/ nmtcc/

Roadmap of the Pylons site

&nmtURL;

All TCC web pages

&nmtAbs;

TCC projects

&tccRel;

&tccProjectsRel;

Pylons projects

virtualenv.py, bin/, include/, lib/

site.xml, .git

config/, controllers/, model/, etc.

&pylonsRel;

&rootRel;

&baseRel;

&projectRel;

&p;

The entities such as &projectRel; are used to refer to these locations in the DocBook source for thisdocument.

• Entities of the form &xxxURL; are URLs starting with “http”.

• Entities of the form &xxxAbs; are absolute path names. For any URL of the form &nmtURL;R, theactual files are located in the absolute path &nmtAbs;R.

• Entities of the form &xxxRel; are paths relative to either &nmtURL; or &nmtAbs;.

The base directory contains the Git repository and the source file for this document. See Section 5, “Filesin the base directory” (p. 6).

The project directory contains the bulk of the application files. Here we find:

• Section 6, “Files in the project directory” (p. 9).

• Section 7, “Configuration files: config/” (p. 9).

• Section 8, “Controllers” (p. 15) are the C part of the MVC (model-view-controller) architecture.

• Section 9, “The lib/ directory” (p. 20) is an area for useful components that are not part of the MVCarchitecture.

• Section 10, “The model/ directory” (p. 24) is the M part of the MVC architecture.

• Section 11, “The public/ directory” (p. 25) is a directory for static pages that we can serve to anyone(whether authenticated or not).

• Section 12, “The templates/ directory” (p. 28) contains view templates, the V part of the MVC ar-chitecture.

• Section 13, “The tests/ directory” (p. 33) contains code for testing.

4.TestingFrequent builds and testing are good. You can run the Pylons site in any of three modes, each with itsown initialization file: development (development.ini), test (test.ini), and production (deploy-ment.ini).

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.04

• Section 4.1, “Activating and deactivating the virtual environment” (p. 5): A separate Python worldfor the server.

• For development mode, see Section 4.2, “Testing in the development environment” (p. 5).

4.1. Activating and deactivating the virtual environmentWhenever you are working on this site, you must first activate the virtual environment. This runs theserver using a completely separate install of Python and many other components, so it does not dependon outside installs.

1. cd /u/www/docs/tcc/projects/pylons/newroot/

2. Be sure you are running bash, because the following step will not work in csh or tcsh.

3. Type this command to activate the virtual environment:

source bin/activate

The prompt will change to “(root)bash-4.0$”.

To exit the virtual environment, use this command:

deactivate

4.2.Testing in the development environmentTo start up the Web server in development mode, first activate the virtual environment (see Section 4.1,“Activating and deactivating the virtual environment” (p. 5)).

1. Move to the base directory.

cd /u/www/docs/tcc/projects/pylons/newroot/NMTCC/

2. Use this command to start a server that will be visible only to Web browsers running on the samehost.

paster serve --reload development.ini

Select the --reload option if you want the server to constantly look at the modification times ofall relevant files, so it will use the latest version of your controllers, models, and so forth.

3. Start a browser on the same host. Beware: if you have a Firefox running anywhere else, and youstart it on the local host, you get another window running from the other host. You may want touse Konqueror or something other than your usual browser, to make sure it is running on the correcthost.

4. Bring up either one of these URLs in the local browser:

http://localhost:5000/http://127.0.0.1:5000/

The port number (5000) is the one set in the current development.ini file, on the line that startswith “host = …”. Note that you need root privileges to use ports numbered less than 1024.

If the server is running properly, you will see the local site. Then try this URL to demonstrate Section 8.5.2,“The info/motd action” (p. 19):

5TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

http://localhost:5000/info/motd

5. Files in the base directoryThe base directory of this project is at this absolute path:

/u/www/docs/tcc/projects/pylons/newroot/NMTCC/

In addition to the source of this DocBook document and the Git repository, this directory contains otherimportant files:

• development.ini, test.ini, and production.ini are the configuration files for the project indevelopment, test, and production modes, respectively.

Because these files contain plaintext passwords, the current versions are not presented here in literateform. They are managed as part of the Git repository. However, for the original, uncustomized files,see Section 5.1, “The stockdev.ini file” (p. 6) and Section 5.2, “The stocktest.ini file” (p. 8).For the uncustomized deployment.ini file, see Section 7.2, “config/deployment.ini_tm-pl” (p. 10).

• Other files and subdirectories created by the paster but not currently customized: MANIFEST.in,NMTCC.egg-info/, README.txt, docs/, ez_setup.py, setup.cfg, and setup.py.

5.1.The stockdev.ini fileThis file controls initialization when the development environment is started up. Because it containspasswords, the current version is not presented here or archived in the Git repository.

Here is the uncustomized file, stockdev.ini. See below for a current list of the changes made to it sofar.

stockdev.ini

## NMTCC - Pylons development environment configuration## The %(here)s variable will be replaced with the parent directory# of this file#[DEFAULT]debug = true# Uncomment and replace with the address which should receive any# error reports#email_to = [email protected]_server = localhosterror_email_from = paste@localhost

[server:main]use = egg:Paste#httphost = 127.0.0.1port = 5000

[app:main]use = egg:NMTCCfull_stack = true

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.06

static_files = true

cache_dir = %(here)s/databeaker.session.key = nmtccbeaker.session.secret = somesecret

# If you'd like to fine-tune the individual locations of the cache# data dirs for the Cache data, or the Session saves, un-comment# the desired settings here:#beaker.cache.data_dir = %(here)s/data/cache#beaker.session.data_dir = %(here)s/data/sessions

# SQLAlchemy database URLsqlalchemy.url = sqlite:///%(here)s/development.db

# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*# Debug mode will enable the interactive debugging tool, allowing ANYONEto# execute malicious code after an exception is raised.#set debug = false

# Logging configuration[loggers]keys = root, routes, nmtcc, sqlalchemy

[handlers]keys = console

[formatters]keys = generic

[logger_root]level = INFOhandlers = console

[logger_routes]level = INFOhandlers =qualname = routes.middleware# "level = DEBUG" logs the route matched and routing variables.

[logger_nmtcc]level = DEBUGhandlers =qualname = nmtcc

[logger_sqlalchemy]level = INFOhandlers =qualname = sqlalchemy.engine# "level = INFO" logs SQL queries.# "level = DEBUG" logs SQL queries and results.# "level = WARN" logs neither. (Recommended for production systems.)

7TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

[handler_console]class = StreamHandlerargs = (sys.stderr,)level = NOTSETformatter = generic

[formatter_generic]format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)sdatefmt = %H:%M:%S

These changes have been made to the uncustomized version:

1. email_to: Change the list of people emailed with error reports.

2. beaker.session.secret: Create a password for the Beaker session.

3. sqlalchemy.url: Set this to the URL of the database server using SQLAlchemy syntax.

4. Add these lines at the end of the [app:main] section to configure authorization, replacing the valueof authkit.cookie.secret by a long string of random characters.

authkit.setup.method = forward, cookieauthkit.cookie.secret = xxxxxxxxxxxxxxxxauthkit.cookie.includeip = Trueauthkit.cookie.signoutpath = /nmtcc/acct/logoutauthkit.forward.signinpath = /nmtcc/acct/loginauthkit.cookie.params.max-age = 14400authkit.cookie.params.expires = 14400authkit.cookie.enforce = True

5.2.The stocktest.ini fileThis file controls initialization of the test environment. It is not presented here in literate form, becauseeventually it will contain live passwords. Here is the uncustomized file:

stocktest.ini

## NMTCC - Pylons testing environment configuration## The %(here)s variable will be replaced with the parent directory# of this file#[DEFAULT]debug = true# Uncomment and replace with the address which should receive any# error reports#email_to = [email protected]_server = localhosterror_email_from = paste@localhost

[server:main]use = egg:Paste#httphost = 127.0.0.1

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.08

port = 5000

[app:main]use = config:development.ini

# Add additional test specific configuration options as necessary.

6. Files in the project directoryThese files are located in the nmtcc/ subdirectory under the base directory /u/www/docs/tcc/pro-jects/pylons/newroot/NMTCC/.

6.1. __init__.pyCreated empty by the paster.

nmtcc/__init__.py

6.2. websetup.pyAs created by the paster.

nmtcc/websetup.py

"""Setup the NMTCC application"""import logging

import pylons.test

from nmtcc.config.environment import load_environmentfrom nmtcc.model.meta import Session, Base

log = logging.getLogger(__name__)

def setup_app(command, conf, vars):"""Place any commands to setup nmtcc here"""# Don't reload the app if it was loaded under the testing environmentif not pylons.test.pylonsapp:

load_environment(conf.global_conf, conf.local_conf)

# Create the tables if they don't already existBase.metadata.create_all(bind=Session.bind)

7. Configuration files: config/These files are created by paste create, but have now been moved into literate form here.

7.1. config/__init__.pyCreated empty by the paster.

9TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

nmtcc/config/__init__.py

7.2. config/deployment.ini_tmplAs created by the paster.

nmtcc/config/deployment.ini_tmpl

## NMTCC - Pylons configuration## The %(here)s variable will be replaced with the parent directory# of this file#[DEFAULT]debug = trueemail_to = [email protected]_server = localhosterror_email_from = paste@localhost

[server:main]use = egg:Paste#httphost = 0.0.0.0port = 5000

[app:main]use = egg:NMTCCfull_stack = truestatic_files = true

cache_dir = %(here)s/databeaker.session.key = nmtccbeaker.session.secret = ${app_instance_secret}app_instance_uuid = ${app_instance_uuid}

# If you'd like to fine-tune the individual locations of the cache# data dirs for the Cache data, or the Session saves, un-comment# the desired settings here:#beaker.cache.data_dir = %(here)s/data/cache#beaker.session.data_dir = %(here)s/data/sessions

# SQLAlchemy database URLsqlalchemy.url = sqlite:///production.db

# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION# ENVIRONMENT*# Debug mode will enable the interactive debugging tool, allowing# ANYONE to execute malicious code after an exception is raised.set debug = false

# Logging configuration[loggers]keys = root

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.010

[handlers]keys = console

[formatters]keys = generic

[logger_root]level = INFOhandlers = console

[handler_console]class = StreamHandlerargs = (sys.stderr,)level = NOTSETformatter = generic

[formatter_generic]format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s]%(message)s

7.3. config/environment.pyAs created by the paster.

nmtcc/config/environment.py

"""Pylons environment configuration"""import os

from genshi.template import TemplateLoaderfrom pylons.configuration import PylonsConfigfrom sqlalchemy import engine_from_config

import nmtcc.lib.app_globals as app_globalsimport nmtcc.lib.helpersfrom nmtcc.config.routing import make_mapfrom nmtcc.model import init_model

def load_environment(global_conf, app_conf):"""Configure the Pylons environment via the ``pylons.config``object"""config = PylonsConfig()

# Pylons pathsroot = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))paths = dict(root=root,

controllers=os.path.join(root, 'controllers'),static_files=os.path.join(root, 'public'),templates=[os.path.join(root, 'templates')])

# Initialize config with the basic optionsconfig.init_app(global_conf, app_conf, package='nmtcc', paths=paths )config['routes.map'] = make_map(config)

11TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

config['pylons.app_globals'] = app_globals.Globals(config)config['pylons.h'] = nmtcc.lib.helpers

# Setup cache object as early as possibleimport pylonspylons.cache._push_object(config['pylons.app_globals'].cache)

# Create the Genshi TemplateLoaderconfig['pylons.app_globals'].genshi_loader = TemplateLoader(

paths['templates'], auto_reload=True)

# Setup the SQLAlchemy database engineengine = engine_from_config(config, 'sqlalchemy.')init_model(engine)

# CONFIGURATION OPTIONS HERE (note: all config options will override# any Pylons config options)

return config

7.4. config/middleware.pyThis file sets up the middleware for the application. A good reference to this is the Pylons book7, chapter16 (WSGI). Essentially, middleware sits between the server and the application and can intercept ormodify the HTTP request or response.

The first section is from the uncustomized file as it is created by the paster8.nmtcc/config/middleware.py

"""Pylons middleware initialization"""from beaker.middleware import SessionMiddlewarefrom paste.cascade import Cascadefrom paste.registry import RegistryManagerfrom paste.urlparser import StaticURLParserfrom paste.deploy.converters import asboolfrom pylons.middleware import ErrorHandler, StatusCodeRedirectfrom pylons.wsgiapp import PylonsAppfrom routes.middleware import RoutesMiddleware

We'll need the authentication middleware from AuthKit9. 10

nmtcc/config/middleware.py

import authkitimport authkit.authenticate

The next section is unmodified.

7 http://pylonsbook.com/en/1.1/8 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/as_pasted/middleware.py9 http://authkit.org/10 According to Mike Orr, who is one of the principal Pylons developers, the recent (2010) trend is toward using repoze.who[http://static.repoze.org/whodocs/] for authentication and repoze.what [http://what.repoze.org/docs/1.0/] for authorization. However,at this writing, Bryan Hughes had a fully working Pylons application that uses Kerberos, which makes a good model.

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.012

nmtcc/config/middleware.py

from nmtcc.config.environment import load_environment

def make_app(global_conf, full_stack=True, static_files=True, **app_conf):

"""Create a Pylons WSGI application and return it

``global_conf``The inherited configuration for this application. Normally fromthe [DEFAULT] section of the Paste ini file.

``full_stack``Whether this application provides a full WSGI stack (by default,meaning it handles its own exceptions and errors). Disablefull_stack when this application is "managed" by another WSGImiddleware.

``static_files``Whether this application serves its own static files; disablewhen another web server is responsible for serving them.

``app_conf``The application's local configuration. Normally specified inthe [app:<name>] section of the Paste ini file(where <name> defaults to main).

"""# Configure the Pylons environmentconfig = load_environment(global_conf, app_conf)

# The Pylons WSGI appapp = PylonsApp(config=config)

# Routing/Session Middlewareapp = RoutesMiddleware(app, config['routes.map'], singleton=False)app = SessionMiddleware(app, config)

# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)

This next section has been locally modified. The line after the comment “Handle Python exceptions”inserts the AuthKit authentication middleware into the stack just ahead of the standard ErrorHandlermiddleware.

nmtcc/config/middleware.py

if asbool(full_stack):# Handle Python exceptionsapp = authkit.authenticate.middleware(app, app_conf)app = ErrorHandler(app, global_conf, **config['pylons.errorware'])

# Display error documents for 401, 403, 404 status codes (and# 500 when debug is disabled)if asbool(config['debug']):

app = StatusCodeRedirect(app)

13TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

else:app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])

The Pylons book11 notes in chapter 18, “Authentication and authorization,” that if the .ini file sets thefull_stack option to False, the above modification must be moved to a position just before thecomment that says “CUSTOM MIDDLEWARE HERE.”

The rest is uncustomized.nmtcc/config/middleware.py

# Establish the Registry for this applicationapp = RegistryManager(app)

if asbool(static_files):# Serve static files

static_app = StaticURLParser(config['pylons.paths']['static_files'])

app = Cascade([static_app, app])app.config = configreturn app

7.5. config/routing.pySee the online documentation for Routes12.

The first part is as created by the paster.nmtcc/config/routing.py

"""Routes configuration

The more specific and detailed routes should be defined first so theymay take precedent over the more generic routes. For more informationrefer to the routes manual at http://routes.groovie.org/docs/"""from routes import Mapper

def make_map(config):"""Create, configure and return the routes Mapper"""map = Mapper(directory=config['pylons.paths']['controllers'],

always_scan=config['debug'])map.minimization = Falsemap.explicit = False

# The ErrorController route (handles 404/500 error pages); it should# likely stay at the top, ensuring it can always be resolvedmap.connect('/error/{action}', controller='error')map.connect('/error/{action}/{id}', controller='error')

# CUSTOM ROUTES HERE

For any URL with a controller but no action, use index as the default action.

11 http://pylonsbook.com/en/1.1/12 http://pylonshq.com/docs/en/1.0/thirdparty/routes/

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.014

nmtcc/config/routing.py

map.connect('/{controller}', action='index')

The next two rules are as the paster created them.nmtcc/config/routing.py

map.connect('/{controller}/{action}')map.connect('/{controller}/{action}/{id}')

When users add an extra "/" at the end of a route, we should ignore it. There is an elegant solution tothis online13: at the end, after all the other routes have been mapped, add a map.redirect() rule thatmatches any route ending with a slash, and redirects it to the same route without the slash.

nmtcc/config/routing.py

#--# Ignore any route ending with a slash.#--map.redirect('/*(url)/', '/{url}',

_redirect_code='301 Moved permanently')

The last line, as it comes from the paster, returns the constructed map.nmtcc/config/routing.py

return map

8. ControllersThe controllers/ directory contains the controller components of the MVC. See Section 8.1, “Howto add a new controller” (p. 15).

Here are the controllers for this site:

• Section 8.3, “controllers/acct.py: Authenticated account operations” (p. 16): Authenticatedservices for accountholders: change passwords, change mail forwarding, and so forth.

• Section 8.4, “controllers/error.py” (p. 18): The error controller. This is the only controller createdinitially by the paster create command.

• Section 8.5, “controllers/info.py: Public information controller” (p. 19): Delivers general in-formation about the TCC to the general public. Viewing these pages does not require authentication.

8.1. How to add a new controllerTo create a new controller named nmtcc/controllers/C.py, start in the base directory.

1. cd /u/www/docs/tcc/projects/pylons/newroot/NMTCC/

2. paster controller C

This will also create a skeleton test file as “nmtcc/tests/functional/test_C.py”.

Rather than archiving each original controller and test file as it was created by the paster, we will presentexamples of these two files, as they would be created by the command “paster controller foo”.First, the controller:

13 http://stackoverflow.com/questions/235191/trailing-slashes-in-pylons-routes

15TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

nmtcc/controllers/foo.py

import logging

from pylons import request, response, session, tmpl_context as c, urlfrom pylons.controllers.util import abort, redirect

from nmtcc.lib.base import BaseController, render

log = logging.getLogger(__name__)

class FooController(BaseController):

def index(self):# Return a rendered template#return render('/foo.mako')# or, return a stringreturn 'Hello World'

Here is the uncustomized test module:nmtcc/tests/functional/test_foo.py

from nmtcc.tests import *

class TestFooController(TestController):

def test_index(self):response = self.app.get(url(controller='foo', action='index'))# Test response...

8.2. controllers/__init__.pyCreated as empty by the paster.

nmtcc/controllers/__init__.py

8.3. controllers/acct.py: Authenticated account operationsThis entire controller is protected so that the user must login with their TCC account name and passwordbefore executing any action of the controller.

Actions within this controller:

• Section 8.3.1, “The acct/index action” (p. 17): The start page.

• Section 8.3.2, “The acct/newpass action: Change your password” (p. 17): Change your password.

The initial section is uncustomized except for a module documentation string.nmtcc/controllers/acct.py

'''controllers/acct.py: Authenticated user account operations.'''import logging

from pylons import request, response, session, tmpl_context as c, urlfrom pylons.controllers.util import abort, redirect

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.016

from nmtcc.lib.base import BaseController, render

log = logging.getLogger(__name__)

We'll also need to import the authorization decorator from AuthKit, and the RemoteUser permission.nmtcc/controllers/acct.py

from authkit.authorize.pylons_adaptors import authorizefrom authkit.permissions import RemoteUser

As described in the Pylons book14, to protect the entire controller from use by unauthenticated users,we add a .__before__() method that will be executed before any action. The @authorize() decor-ator, used with the RemoteUser() permission, checks to see if the REMOTE_USER has a value in theenvironment and, if not, the authentication middleware will present the user with a login page.

nmtcc/controllers/acct.py

# - - - - - c l a s s A c c t C o n t r o l l e r

class AcctController(BaseController):

# - - - A c c t C o n t r o l l e r . _ _ b e f o r e _ _

@authorize(RemoteUser())def __before__(self):

pass

8.3.1.The acct/index action

This action presents the initial page once the user is authenticated. For the related template, see Sec-tion 12.5, “The acct.html template” (p. 31).

nmtcc/controllers/acct.py

# - - - a c c t / i n d e x

def index(self):'''Start page for the account services area.'''c.title = "Services for your Tech Computer Center account"return render('/acct.html')

8.3.2.The acct/newpass action: Change your password

For the associated template, see Section 12.9, “The newpass.html view: Change your password” (p. 32).nmtcc/controllers/acct.py

# - - - a c c t / n e w p a s s

def newpass(self):'''Change your password.'''

14 http://pylonsbook.com/en/1.1/

17TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

c.title = "Change your password"return render('/newpass.html')

8.4. controllers/error.pyAs created by the paster.

nmtcc/controllers/error.py

import cgi

from paste.urlparser import PkgResourcesParserfrom pylons.middleware import error_document_templatefrom webhelpers.html.builder import literal

from nmtcc.lib.base import BaseController

class ErrorController(BaseController):"""Generates error documents as and when they are required.

The ErrorDocuments middleware forwards to ErrorController when errorrelated status codes are returned from the application.

This behaviour can be altered by changing the parameters to theErrorDocuments middleware in your config/middleware.py file.

"""def document(self):

"""Render the error document"""request = self._py_object.requestresp = request.environ.get('pylons.original_response')content = literal(resp.body) or cgi.escape(

request.GET.get('message', ''))page = error_document_template % \

dict(prefix=request.environ.get('SCRIPT_NAME', ''),code=cgi.escape(request.GET.get('code',

str(resp.status_int))),message=content)

return page

def img(self, id):"""Serve Pylons' stock images"""return self._serve_file('/'.join(['media/img', id]))

def style(self, id):"""Serve Pylons' stock stylesheets"""return self._serve_file('/'.join(['media/style', id]))

def _serve_file(self, path):"""Call Paste's FileApp (a WSGI application) to serve the fileat the specified path"""request = self._py_object.requestrequest.environ['PATH_INFO'] = '/%s' % path

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.018

return PkgResourcesParser('pylons', 'pylons')(request.environ,self.start_response)

8.5. controllers/info.py: Public information controllerThe actions in this controller serve general TCC information to unauthenticated users. The first sectionhere is as the paster created it.

nmtcc/controllers/info.py

'''controllers/info.py: General public information actions.'''import logging

from pylons import request, response, session, tmpl_context as c, urlfrom pylons.controllers.util import abort, redirect

from nmtcc.lib.base import BaseController, render

We'll also need to import the helpers from lib/helpers.py.nmtcc/controllers/info.py

import nmtcc.lib.helpers as h

The next block is as it came out of the paster.nmtcc/controllers/info.py

log = logging.getLogger(__name__)

# - - - - - c l a s s I n f o C o n t r o l l e r

class InfoController(BaseController):

8.5.1.The info/index action

The index controller created by the paster simply returned the string 'Hello World'. Instead, thecode below will attempt to render the test template, /page.html.

nmtcc/controllers/info.py

# - - - i n f o / i n d e x

def index(self):c.title = "Welcome to the New Mexico Tech Computer Center"return render('page.html')

8.5.2.The info/motd action

This action presents the Message of the Day as a preformatted block. It uses Section 9.4.3, “h.motd():Message of the day” (p. 23) and Section 12.8, “The motd.html view” (p. 32).

nmtcc/controllers/info.py

# - - - i n f o / m o t d

def motd(self):'''Display the message of the day.

19TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

[ /etc/motd exists and is world-readable ->render motd.html showing /etc/motd's contents ]

'''c.title = "Message of the day: %s" % h.timeNow()return render('motd.html')

9.The lib/ directory

9.1. lib/__init__.pyCreated empty by the paster.

nmtcc/lib/__init__.py

9.2. lib/app_globals.pyAs created by the paster.

nmtcc/lib/app_globals.py

"""The application's Globals object"""

from beaker.cache import CacheManagerfrom beaker.util import parse_cache_config_options

class Globals(object):

"""Globals acts as a container for objects available throughout thelife of the application

"""

def __init__(self, config):"""One instance of Globals is created during applicationinitialization and is available during requests via the'app_globals' variable

"""self.cache = CacheManager(**parse_cache_config_options(config))

9.3. lib/base.pyAs created by the paster.

nmtcc/lib/base.py

"""The base Controller API

Provides the BaseController class for subclassing."""from pylons.controllers import WSGIControllerfrom pylons.templating import render_genshi as render

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.020

from nmtcc.model.meta import Session

class BaseController(WSGIController):

def __call__(self, environ, start_response):"""Invoke the Controller"""# WSGIController.__call__ dispatches to the Controller method# the request is routed to. This routing information is# available in environ['pylons.routes_dict']try:

return WSGIController.__call__(self, environ, start_response)finally:

Session.remove()

9.4. lib/helpers.pyThe prologue, here, was created by the paster.

nmtcc/lib/helpers.py

"""Helper functions

Consists of functions to typically be used within templates, but alsoavailable to Controllers. This module is available to templates as 'h'."""# Import helpers as desired, or define your own, ie:#from webhelpers.html.tags import checkbox, password

9.4.1. Imports for lib/helpers.py

The standard Python datetime module provides clock and calendar functions; the standard timemodule gives us access to the local time settings. See the datetime15 and time16 module documentationfor particulars.

nmtcc/lib/helpers.py

#================================================================# Imported modules#----------------------------------------------------------------import datetimeimport time as _time

A number of useful functions for HTML generation come from the WebHelpers17 package, in the web-helpers.html.tags submodule.

• end_form(): Generates the closing tag for a form.• hidden(): Generates a hidden form element.• link_to(): Generates an a tag.• password(): Generates a password form field.• select(): Generates a selection list form element.• stylesheet_link(): Link to a CSS stylesheet.

15 http://docs.python.org/library/datetime.html16 http://docs.python.org/library/time.html17 http://wiki.pylonshq.com/docs/en/0.9.7/thirdparty/webhelpers/

21TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

• submit(): Generates a submit button.• text(): Generates a text entry form element.

We also use webhelpers.secure_form.secure_form() to put up forms that contain a hiddenfield that carries the authentication token. The online reference documentation18 for this module incor-rectly claims that this function is in webhelpers.html.secure_form, but with the 1.0 release it wasmoved to webhelpers.pylonslib.secure_form because it depends on Pylons, while WebHelpersis technically a standalone product. For details of this move, joingroups.google.com/group/pylons-discuss and find the thread19 entitled “Problem with h.se-cure_form after upgrade to pylons 1.0”.

nmtcc/lib/helpers.py

from webhelpers.html.tags import *from webhelpers.pylonslib.secure_form import secure_form

9.4.2.The LocalTimeZone class

In order to work with the datetime library, we must define a class that defines the characteristics oflocal time. This code was stolen pretty much intact from the datetime documentation20.

nmtcc/lib/helpers.py

# [ STDOFFSET := a datetime.timedelta representing the local# zone offset during standard time# DSTOFFSET := a datetime.timedelta representing the local# zone offset during daylight time# DSTDIFF := a datetime.timedelta representing the difference# between daylight and standard time# ZERO := a datetime.timedelta representing no offset ]ZERO = datetime.timedelta(0)STDOFFSET = datetime.timedelta(seconds=(-_time.timezone))DSTOFFSET = ( datetime.timedelta(seconds=(-_time.altzone))

if _time.daylightelse STDOFFSET)

DSTDIFF = DSTOFFSET - STDOFFSET

# [ STDOFFSET := a datetime.timedelta representing the local# zone offset during standard time# DSTOFFSET := a datetime.timedelta representing the local# zone offset during daylight time# DSTDIFF := a datetime.timedelta representing the difference# between daylight and standard time# ZERO := a datetime.timedelta representing no offset ]ZERO = datetime.timedelta(0)STDOFFSET = datetime.timedelta(seconds=(-_time.timezone))DSTOFFSET = ( datetime.timedelta(seconds=(-_time.altzone))

if _time.daylightelse STDOFFSET )

DSTDIFF = DSTOFFSET - STDOFFSET

# - - - - - c l a s s L o c a l T i m e Z o n e

18 http://wiki.pylonshq.com/19 http://groups.google.com/group/pylons-discuss/browse_thread/thread/f3e8b04db35a34ef/20 http://docs.python.org/library/datetime.html

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.022

class LocalTimeZone(datetime.tzinfo):'''Time zone information for local time.'''def utcoffset(self, dt):

'''Returns the current local time offset.'''if self._isdst(dt): return DSTOFFSETelse: return STDOFFSET

def dst(self, dt):'''Returns the additional offset to use during daylight time.'''if self._isdst(dt): return DSTDIFFelse: return ZERO

def tzname(self, dt):'''Returns the time zone name'''return _time.tzname[self._isdst(dt)]

def _isdst(self, dt):'''Is it daylight savings time now?'''#-- 1 --# [ stamp := an epoch time representing dt but with the DST# flag set as unknown (-1) ]]stamp = _time.mktime ( (dt.year, dt.month, dt.day, dt.hour,

dt.minute, dt.second, dt.weekday(), 0, -1) )

#-- 2 --# [ tt := stamp as a _time "time tuple" ]tt = _time.localtime(stamp)

#-- 3 --# [ if tt is daylight time -># return True# else -> return False ]return tt.tm_isdst > 0

Finally, we create a LocalTimeZone instance that will be used in Section 9.4.4, “h.timeNow(): Dateand time for humans” (p. 24).

nmtcc/lib/helpers.py

tzLocal = LocalTimeZone()

9.4.3. h.motd(): Message of the day

This helper function is used by Section 8.5.2, “The info/motd action” (p. 19).nmtcc/lib/helpers.py

# - - - h . m o t d

def motd():'''Returns the Message of the Day.

23TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

[ /etc/motd exists and is world-readable ->return the contents of /etc/motd as a string ]

'''with open('/etc/motd') as inFile:

contents = inFile.read()return contents

9.4.4. h.timeNow(): Date and time for humans

Returns a string of this form:

Wed 2010-04-28 19:32 MDT

Python's datetime module does not document the format codes for datetime.strftime(), buthere are the relevant values:

• %a: Day of the week, abbreviated.• %F: Date as YYYY-MM-DD.• %R: Time as HH:MM.• %Z: Time zone abbreviation.

nmtcc/lib/helpers.py

# - - - h . t i m e N o w

def timeNow():'''Returns the current date and local time.'''#-- 1 --# [ now := a datetime.datetime instance representing now# as local time ]now = datetime.datetime.now(tzLocal)

#-- 2 --return now.strftime( "%a %F %R %Z" )

10.The model/ directoryContains the model components of the MVC.

10.1. model/__init__.pyAs created by the paster.

nmtcc/model/__init__.py

"""The application's model objects"""from nmtcc.model.meta import Session, Base

def init_model(engine):"""Call me before using any of the tables or classes in the model"""Session.configure(bind=engine)

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.024

10.2. model/meta.pyAs created by the paster.

nmtcc/model/meta.py

"""SQLAlchemy Metadata and Session object"""from sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import scoped_session, sessionmaker

__all__ = ['Base', 'Session']

# SQLAlchemy session manager. Updated by model.init_model()Session = scoped_session(sessionmaker())

# The declarative BaseBase = declarative_base()

11.The public/ directoryIn addition to some graphics files (bg.png, favicon.ico, and pylons-logo.gif), this directorycontains a default index.html. Until it is replaced, it is presented here.

nmtcc/public/index.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html

PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>

<title>Welcome to Pylons!</title><style type="text/css">

body {font-family: arial, helvetica, sans-serif;background-color: #ffc900;background-image: url(bg.png);background-repeat: repeat-x;width:100%;height:100%;margin:0;max-height: 100%;padding:0;border:none;line-height:1.4;

}#container {

color:white;background-color:#111;position: absolute;left: 50%;width: 500px;margin-left: -300px;padding:50px;height:100%;

25TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

}#footer {

margin: 120px 0 0 0;padding: 3px;text-align:center;font-size:small;background-color:#222;letter-spacing: 1px;

}h1 {

text-align:center;font-size:xx-large;font-weight:normal;margin: 0 0 20px 0;border:none;padding:0;letter-spacing: 5px;

}h2 {

font-size:xx-large;font-weight:normal;margin: 0 0 20px 0;border:none;padding:0;

}hr {

margin-bottom:30px;border: 1px solid #222;background-color: #222;padding: 2px;

}#logo {

background-image: url(signum8b_spk.png);background-repeat: no-repeat;height: 0;overflow: hidden;padding-top: 99px;width: 239px;

}#left {

float:left;width:250px;margin:0 50px 0 0;border:none;padding:0 0 0 10px;

}#right {

margin:0 0 0 330px;border:none;padding:0;

}ul {

list-style:none;

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.026

margin:0;border:none;padding:0;

}a:visited {

color:white;text-decoration:none;

}a:link {

color:white;text-decoration:none;

}</style></head><body>

<div id="container"><h1>Welcome to <img src="pylons-logo.gif" alt="Logo displaying

the word Pylons"style="vertical-align:-15px; width: 250px;"/>

</h1><hr/><div id="left">

<h2>Let's begin!</h2><p>If you haven't used Pylons before, start with the <a

href="http://pylonshq.com/docs/en/1.0/gettingstarted/"style="text-decoration:underline;">beginners'

tutorial</a>.</p></div><div id="right">

<h2>Help</h2><ul>

<li><a href="http://pylonshq.com/docs/en/1.0/">Official

documentation</a></li><li>

<ahref="http://wiki.pylonshq.com/display/pylonsfaq/Home">FAQ</a>

</li><li>

<ahref="http://wiki.pylonshq.com/dashboard.action">Wiki</a>

</li><li>

<ahref="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-JointheMailingLists">Mailinglist</a>

</li><li>

<ahref="http://wiki.pylonshq.com/display/pylonscommunity/Home#Home-IRC">IRC</a>

</li><li>

27TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

<ahref="http://pylonshq.com/project/pylonshq/roadmap">Bug tracker</a>

</li></ul>

</div><div id="footer">

<a href="http://www.pylonshq.com" style="color: #ccc;text-decoration:none;"

>www.pylonshq.com</a></div>

</div></body>

</html>

11.1. public/tccstyle.css:The local stylesheetOur CSS is built on top of YUI21. Their stylesheet reset-fonts-grids.css, which lives innmtcc/public/yui/2.8.0/reset-fonts-grids/, resets browser styles and defines a grid layout.We invoke that stylesheet here:

nmtcc/public/tccstyle.css

/* NMTCC site base stylesheet. For documentation, see:* http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/*/

@import "yui/2.8.0/reset-fonts-grids/reset-fonts-grids.css";@import "yui/2.8.0/base/base-min.css";

The rest of this file is a combination of snippets taken from the YUI base stylesheet and local modific-ations.

These rules set the body background and foreground colors: a pale yellow and a coffee brown.nmtcc/public/tccstyle.css

html{ background-color: #fff9d1;color: #663300;

}

In the table used to format the page heading in Section 12.3, “templates/base.html: The top-levelsite template” (p. 29), the td elements have class hd_cell. These rules force no padding, and suppressborders around the cells.

nmtcc/public/tccstyle.css

td.hd_cell{ border-width: 0px;padding-left: 0px;

}

12.The templates/ directoryContains view templates (as opposed to project templates).

21 http://developer.yahoo.com/yui/

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.028

You may find these resources valuable:

• Genshi 0.6.x documentation22, especially the Genshi XML Template Language23 documentation.• The Genshi templates section24 of the Pylons Cookbook25.• Our base for CSS is the YUI Library26, as recommended in The Definitive Guide to Pylons. This base

addresses a number of browser compatibility issues and provides a general-purpose grid-based layout.

Although there is a v3.1 release, apparently the CSS Grids module is deprecated, and it is unclear atthis writing (April 2010) what will succeed it. Hence, we will use the v2.8.0r4 release.

See Section 12.1, “How to add a new template” (p. 29). Here is the current set of templates:

• Section 12.3, “templates/base.html: The top-level site template” (p. 29) is the top-level templatethat enforces our standard page features.

• Section 12.4, “templates/page.html: Sample view template” (p. 31) is an empty page template;start a new template by copying this file.

The remaining templates are shown here in alphabetical order.• Section 12.5, “The acct.html template” (p. 31).• Section 12.8, “The motd.html view” (p. 32).• Section 12.9, “The newpass.html view: Change your password” (p. 32).

12.1. How to add a new templateTo add a new template to the project:

1. Create a new second-level section in this document. Tag it with an attribute of the formid='v-name' where name is the name of the template without the trailing “.html”.

2. Add a link to the new section in Section 12, “The templates/ directory” (p. 28).

3. Start the new template code by copying templates/page.html27. Use a CDATA section, unlessyou want to replace all the “<” characters with “&lt;”.

4. Repalce the “Under construction” paragraph with the body of the page.

12.2. templates/__init__.pyCreated empty by the paster.

nmtcc/templates/__init__.py

12.3. templates/base.html:The top-level site templateThis template is the top-level template for the site. Its structure is derived from the example in the PylonsCookbook.

The DOCTYPE comes from the recommendation of the YUI CSS library, except we substitute XHTML1.1 for HTML 4.01. We define three namespace prefixes:

• The blank namespace is XHTML.

22 http://genshi.edgewall.org/wiki/Documentation/0.6.x/index.html23 http://genshi.edgewall.org/wiki/Documentation/0.6.x/xml-templates.html24 http://wiki.pylonshq.com/display/pylonscookbook/Genshi+templates25 http://wiki.pylonshq.com/display/pylonscookbook/26 http://developer.yahoo.com/yui/27 http://www.nmt.edu/tcc/projects/pylons/newroot/NMTCC/nmtcc/templates/base.html

29TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

• py: is the Genshi namespace.• xi: is for XInclude, which Genshi uses to reference parent templates.

nmtcc/templates/base.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://genshi.edgewall.org/"xmlns:xi="http://www.w3.org/2001/XInclude"lang="en"py:strip="">

The final py:strip="" causes the html element to removed when this template is invoked by another.

The rest of the template comes from the Pylons Cookbook, with these changes:

• The body is structured using YUI's header-body-footer convention. The relevant stylesheet rules are#hd, #bd, and #ft for the header, body, and footer divs, respectively.

• The original cookbook had this line:

<meta py:replace="select('*|text()')" />

However, unless we need to add other meta elements to a specific view, we'll omit this here.• The cookbook example required each view template to include a meta element specifying the page's

content type and encoding, and linking to the appropriate stylesheet.

However, under the assumption that all pages will have the same content type, encoding, andstylesheet, we'll include that information here, to give a single point of authority for these critical at-tributes.

nmtcc/templates/base.html

<head py:match="head" py:attrs="select('@*')"><meta http-equiv="content-type"

content="text/html; charset=utf-8" /><link rel="stylesheet" type="text/css"

href="/tccstyle.css"py:attrs="{'href': '/tccstyle.css'}" />

<title>${c.title}</title></head><body py:match="body" py:attrs="select('@*')"><div id="doc"><div id="hd"><table width="100%" class="hd_table"><col align="justify" valign="top" width="1*"/><col valign="top" width="250px"/><tr><td class="hd_cell"><h1>${c.title}</h1>

</td><td class="hd_cell"><img src="/logo.png" alt="NMTCC logo"/>

</td></tr>

</table><hr />

</div>

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.030

<div id="bd"><div py:replace="select('*|text()')" />

</div><div id="ft"><hr /><a href="mailto:[email protected]">Contact us</a> |<a href="http://www.nmt.edu/tcc/projects/webframe">Documentation for this site</a>

</div></div>

</body></html>

12.4. templates/page.html: Sample view templateThis template is used by the info/index controller.

Again, this template is derived from the example from the Pylons Cookbook.nmtcc/templates/page.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://genshi.edgewall.org/"xmlns:xi="http://www.w3.org/2001/XInclude"lang="en">

<xi:include href="base.html" /><head/><body><p>Under construction.</p>

</body></html>

12.5.The acct.html templateThis is the template for Section 8.3.1, “The acct/index action” (p. 17).

nmtcc/templates/acct.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://genshi.edgewall.org/"xmlns:xi="http://www.w3.org/2001/XInclude"lang="en">

<xi:include href="base.html" /><head/><body>

<ul><li>${h.link_to('Change your password',

url(controller='acct', action='newpass'))}</li>

</ul>

31TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

</body></html>

12.6.The login.html viewThis template is used by AuthKit to get the user to log in. See the configuration notes in Section 5.1, “Thestockdev.ini file” (p. 6).

12.7.The logout.html viewThis template is used by AuthKit to log the user out. See the configuration notes in Section 5.1, “Thestockdev.ini file” (p. 6).

12.8.The motd.html viewThis template displays the message of the day. It is rendered by Section 8.5.2, “The info/motd ac-tion” (p. 19).

nmtcc/templates/motd.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://genshi.edgewall.org/"xmlns:xi="http://www.w3.org/2001/XInclude"lang="en">

<xi:include href="base.html" /><head/><body><pre>${h.motd()}</pre>

</body></html>

12.9.The newpass.html view: Change your passwordThis template displays a form that lets user change their password. It is used by Section 8.3.2, “Theacct/newpass action: Change your password” (p. 17).

nmtcc/templates/newpass.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://genshi.edgewall.org/"xmlns:xi="http://www.w3.org/2001/XInclude"lang="en">

<xi:include href="base.html" /><head/><body><p>To change your password...</p>

</body></html>

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.032

13.The tests/ directory

13.1. tests/__init__.pyAs created by the paster.

nmtcc/tests/__init__.py

"""Pylons application test package

This package assumes the Pylons environment is already loaded, such aswhen this script is imported from the `nosetests --with-pylons=test.ini`command.

This module initializes the application via ``websetup`` (`pastersetup-app`) and provides the base testing objects."""from unittest import TestCase

from paste.deploy import loadappfrom paste.script.appinstall import SetupCommandfrom pylons import urlfrom routes.util import URLGeneratorfrom webtest import TestApp

import pylons.test

__all__ = ['environ', 'url', 'TestController']

# Invoke websetup with the current config fileSetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])

environ = {}

class TestController(TestCase):

def __init__(self, *args, **kwargs):wsgiapp = pylons.test.pylonsappconfig = wsgiapp.configself.app = TestApp(wsgiapp)url._push_object(URLGenerator(config['routes.map'], environ))TestCase.__init__(self, *args, **kwargs)

13.2. tests/functional/__init__.pyCreated empty by the paster.

nmtcc/tests/functional/__init__.py

13.3. tests/test_models.pyCreated empty by the paster.

33TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

nmtcc/tests/test_models.py

14. Notes on package installsThis install sequence is a reconstruction from notes taken during the actual installs. The process is ofcourse complicated by the fact that all these packages are under active development, with new minorand major releases in progress.

We use the virtualenv.py package to provide an isolated environment with its own Python andseveral other packages. Refer to the Python Package Index (PyPI)28 for current versions.

14.1. Installing and setting up virtualenv.py1. Retrieve virtualenv.py29 1.4.9 from the PyPI and place it in the directory above where you want

your virtual root to be. Currently this would be:

/u/www/docs/tcc/projects/pylons/

to create directory tcc/projects/pylons/newroot/.

2. In that directory, run this command:

python virtualenv.py --no-site-packages root

This will create directory root containing three subdirectories: bin, include, and lib.

WarningOnce you have done this, you will not be able to tar up the root directory and move it elsewhere:even after activating the virtual environment in the new location, the search path is missing vital com-ponents such as paster. My suspicion is that there are some absolute paths in there somewhere.However, if you need to move the project, you can tar up just the project structure and move that to anew virtual install.

14.2. Pylon and other package installsThese commands must all be done in the virtual environment, after you activate as described in Sec-tion 4.1, “Activating and deactivating the virtual environment” (p. 5).

1. Change to the root directory.

cd /u/www/docs/tcc/projects/pylons/newroot/

2. Install Pylons30.

easy_install 'Pylons==1.0'

3. Install Genshi31.

28 http://pypi.python.org/pypi/29 http://pypi.python.org/pypi/virtualenv/30 http://pylonshq.com/31 http://genshi.edgewall.org/

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.034

easy_install 'Genshi==0.6'

4. Install psycopg232, the Python-Postgres adapter.

easy_install 'psycopg2==2.2.2'

NoteWith a previous version of Pylons, the above step install failed on speare142-1-5 with a gcc error.Bryan Hughes did something magic to install a missing header file. I didn't get the details, but he mayhave to do it again. In the current install, it failed on login, but succeeded on speare142-1-5.

5. Install AuthKit33.

easy_install 'AuthKit==0.4.4'

6. Install SQLAlchemy34.

easy_install 'SQLAlchemy==0.6.3'

7.WarningThe initial project creation used this command sequence. However, don't do this on top of the currentstructure, as it will wipe out of all the DocBook infrastructure.

paster create --template=pylons NMTCC

These responses were given at the prompts:

Enter template_engine: genshiEnter sqlalchemy: True

For customization after this point, refer to the git log inside this project.

14.3. Installing YUIWe use the CSS infrastructure from YUI35. This package doesn't work with easy_install. These in-structions were adapted from page 326 of Gardner's book.

1. cd /u/www/docs/tcc/projects/pylons/newroot/NMTCC/nmtcc/public

2. Go to http://developer.yahoo.com/yui/3/. Use the radiobutton for Full Developer Kit anddownload the archive as yui_3.1.1.zip to the public directory and unzip it, which places itsfiles in subdirectory yui/.

3. cd /u/www/docs/tcc/projects/pylons/newroot/NMTCC/nmtcc/public/yui

32 http://pypi.python.org/pypi/psycopg2/33 http://authkit.org/34 http://www.sqlalchemy.org/35 http://developer.yahoo.com/yui/

35TCC Web framework: Pylons 1.0New Mexico Tech Computer Center

4. Use “rm -r” to remove all the directories under yui except for the build/ subdirectory.

5. Rename the build/ directory with the YUI version. This is an especially good idea because theCSS Grids feature is deprecated in YUI 3.1, and it may be necessary to regress to a 2.x release.

mv build 3.1.1

At this point, the helper routine h.url_for() will expand a pathname starting with“/yui/3.1.1/...” to the directory containing the CSS stylesheets from YUI.

Next, download the older YUI 2.8.0r4 ZIP file, and move its build/ subdirectory to yui/2.8.0/.

New Mexico Tech Computer CenterTCC Web framework: Pylons 1.036