Project

General

Profile

PageMaker » History » Version 2

Elmer de Looff, 2012-05-03 14:47
Initial PageMaker documentation

1 2 Elmer de Looff
h1. Your own PageMaker
2 1 Elmer de Looff
3 2 Elmer de Looff
h1. DebuggingPageMaker
4 1 Elmer de Looff
5 2 Elmer de Looff
h1. Templateparser
6 1 Elmer de Looff
7 2 Elmer de Looff
The µWeb *[[TemplateParser]]* is available on the standard PageMaker instance. When using PageMaker, an instantiated TemplateParser instance is available through the @parser@ member of PageMaker. Basic usage looks like this:
8 2 Elmer de Looff
9 2 Elmer de Looff
<pre><code class="python">
10 2 Elmer de Looff
import uweb
11 2 Elmer de Looff
import time
12 2 Elmer de Looff
13 2 Elmer de Looff
class PageMaker(uweb.PageMaker):
14 2 Elmer de Looff
  def VersionPage(self):
15 2 Elmer de Looff
    return self.parser.Parse(
16 2 Elmer de Looff
      'version.utp', year=time.strftime('%Y'), version=uweb.__version__)
17 2 Elmer de Looff
</code></pre>
18 2 Elmer de Looff
19 2 Elmer de Looff
The example template for the above file could look something like this:
20 2 Elmer de Looff
21 2 Elmer de Looff
<pre><code class="html">
22 2 Elmer de Looff
<!DOCTYPE html>
23 2 Elmer de Looff
<html>
24 2 Elmer de Looff
  <head>
25 2 Elmer de Looff
    <title>µWeb version info</title>
26 2 Elmer de Looff
  </head>
27 2 Elmer de Looff
  <body>
28 2 Elmer de Looff
    <p>µWeb version [version] - Copyright 2010-[year] Underdark</p>
29 2 Elmer de Looff
  </body>
30 2 Elmer de Looff
</html>
31 2 Elmer de Looff
</code></pre>
32 2 Elmer de Looff
33 2 Elmer de Looff
And would result in the following output:
34 2 Elmer de Looff
35 2 Elmer de Looff
<pre><code class="html">
36 2 Elmer de Looff
<!DOCTYPE html>
37 2 Elmer de Looff
<html>
38 2 Elmer de Looff
  <head>
39 2 Elmer de Looff
    <title>µWeb version info</title>
40 2 Elmer de Looff
  </head>
41 2 Elmer de Looff
  <body>
42 2 Elmer de Looff
    <p>µWeb version 0.12 - Copyright 2010-2012 Underdark</p>
43 2 Elmer de Looff
  </body>
44 2 Elmer de Looff
</html>
45 2 Elmer de Looff
</code></pre>
46 2 Elmer de Looff
47 2 Elmer de Looff
Full documentation, with plenty of example template uses can be found on the [[TemplateParser|TemplateParser wiki-entry]].
48 2 Elmer de Looff
49 2 Elmer de Looff
h2. Template directory configuration
50 2 Elmer de Looff
51 2 Elmer de Looff
By default, template are loaded from the 'templates' directory that is expected to be on the same path as the pagemaker module. If your pagemaker is located on @/var/www/uweb_project/project.py@, then templates will be automatically loaded from @/var/www/uweb_project/templates/@.
52 2 Elmer de Looff
53 2 Elmer de Looff
To change the default template loading path, define a new path in the class variable @TEMPLATE_DIR@. This should be a relative path (and defaults to @'templates'@).
54 2 Elmer de Looff
55 2 Elmer de Looff
h1. Static files
56 2 Elmer de Looff
57 2 Elmer de Looff
µWeb can handle Static files from disk by itself, you just need to point the routes to the Static method, and give it the correct path where it can find the resource.
58 2 Elmer de Looff
The mime-type will be discovered automatically by using the Magic libraries avialable on your server.
59 2 Elmer de Looff
60 2 Elmer de Looff
h2. Static directory configuration
61 2 Elmer de Looff
62 2 Elmer de Looff
h1. OpenID routers
63 2 Elmer de Looff
64 2 Elmer de Looff
How to setup routes if you want to use the openID module:
65 2 Elmer de Looff
* ('/OpenIDLogin/?(\w+)?', '_OpenIdInitiate')
66 2 Elmer de Looff
* ('/OpenIDValidate', '_OpenIdValidate')
67 2 Elmer de Looff
68 2 Elmer de Looff
h1. Persistent storage between requests
69 2 Elmer de Looff
70 1 Elmer de Looff
µWeb allows you to store objects in a process-persistent storage. This means that the storage will be properly persistent and available when µWeb is in [[standalone]] mode. When running on top of [[apache]], this persistence is only as good as the apache process, which is typically a couple hundred to a few thousand requests.
71 1 Elmer de Looff
72 2 Elmer de Looff
h2. Default users of the persistent storage
73 1 Elmer de Looff
74 1 Elmer de Looff
By default, the [[TemplateParser]] and the various database connectors are stored in the persistent storage. This has the benefit that pre-parsed templates will not need to be read from disk on subsequent requests. For databases the benefit is that connections need not be made on-the-fly, but can mostly be retrieved from the storage. 
75 1 Elmer de Looff
76 2 Elmer de Looff
h2. Storing persistent values
77 1 Elmer de Looff
78 1 Elmer de Looff
Storing persistent values is done with the @Set@ method, as follows:
79 1 Elmer de Looff
80 1 Elmer de Looff
<pre><code class="python">
81 1 Elmer de Looff
def _PostInit(self):
82 1 Elmer de Looff
  if 'connection' not in self.persistent:
83 1 Elmer de Looff
    self.persistent.Set('connection', self._MakeConnection())
84 1 Elmer de Looff
</code></pre>
85 1 Elmer de Looff
86 1 Elmer de Looff
In the example above, the database connection is only created, and added to the persistent storage, if it's not already present. This way expensive but reusable actions can be optimized by performing them only once (or once every few so many requests, if running on Apache).
87 1 Elmer de Looff
88 2 Elmer de Looff
h2. Retrieving persistent values
89 1 Elmer de Looff
90 1 Elmer de Looff
Retrieving stored values works much like this, but uses the @Get@ method:
91 1 Elmer de Looff
92 1 Elmer de Looff
<pre><code class="python">
93 1 Elmer de Looff
def DatabaseAccess(self):
94 1 Elmer de Looff
  with self.persistent.Get('connection') as cursor:
95 1 Elmer de Looff
    cursor.Execute('INSERT INTO `message` SET `text` = "success!"')
96 1 Elmer de Looff
</code></pre>
97 1 Elmer de Looff
98 1 Elmer de Looff
This uses the connection we created (or still had) during @_PostInit@, and uses it to update the database.
99 1 Elmer de Looff
100 1 Elmer de Looff
In case a key has is not present in the persistent storage (because it wasn't set in the process' lifetime or because it was exlicitly dropped), the @Get@ method has an optional second argument, that is returned when the key is not present:
101 1 Elmer de Looff
102 1 Elmer de Looff
<pre><code class="python">
103 1 Elmer de Looff
def FirstVisit(self):
104 1 Elmer de Looff
  when = self.persistent.Get('first_visit_time', 'just now')
105 1 Elmer de Looff
  return 'Your first visit was %s.' % when
106 1 Elmer de Looff
</code></pre>
107 1 Elmer de Looff
108 1 Elmer de Looff
This will return the stored date and time when there was a previously recorded visit, or the text _just now_ if there was no previous time logged.
109 1 Elmer de Looff
110 1 Elmer de Looff
Finally, the persistent storage has a @SetDefault@ method, that acts much like the similarly named dictionary method. It returns the value for the given key, but if it's not present, it will set the key to the provided value, and return it as well. With this, we can improve on our first-visit tracker, and in one call retrieve or store the first time someone visited:
111 1 Elmer de Looff
112 1 Elmer de Looff
<pre><code class="python">
113 1 Elmer de Looff
def FirstVisit(self):
114 1 Elmer de Looff
  when = self.persistent.SetDefault('first_visit_time', datetime.datetime.now())
115 1 Elmer de Looff
  return 'Your first visit was %s.' % when
116 1 Elmer de Looff
</code></pre>
117 1 Elmer de Looff
118 2 Elmer de Looff
h2. Deleting persistent values
119 1 Elmer de Looff
120 1 Elmer de Looff
If for any reason you need to delete a value from the persistent storage, this can be done using the @Del@ method. The given key name is removed from the storage. *N.B.:* If the key was already removed from the storage (this can happen if the delete code runs more than once, or the key was not defined in the process' lifetime), no error is raised. It is assumed that removing the key is the only desired action.
121 1 Elmer de Looff
122 1 Elmer de Looff
<pre><code class="python">
123 1 Elmer de Looff
def DeletePersistentKey(self, key):
124 1 Elmer de Looff
  self.persistent.Del(key)
125 1 Elmer de Looff
</code></pre>