/dev/docs/infogami
Type: /type/page
body: value: <u><i>This document is not maintained.</i></u>

<p>The Open Library interface is powered by infogami -- a cleaner, simpler alternative to other wiki applications. 
But unlike other wikis, Infogami has the flexibility to handle different classes of data. Most wikis let you store unstructured pages -- big blocks of text. 
Infogami lets you store structured data.

<a name="origin_footnote1">&nbsp;</a><a href="#footnote1" class="footnote">[1]</a>
</p>

<p>In addition to this, infogami facilitates the creation of dynamic HTML templates and macros. This flexible environment enables users to create, share and build collaborative interfaces. With Open Library in particular, we are focused on building a productive and vital community focused on the discovery of books.</p>

<P>Applications are written by extending Infogami through two layers: plugins and templates. Plugins are Python modules that get loaded into Infogami through a special API. (See [an overview of Infogami plugins][6].) They are invoked by submitting HTTP requests to the application, either HTML form posts or direct GET requests. Plugins can use any library or application code that they wish, and they create Python objects to represent results, that then get expanded to HTML by templates. Templates are a mixture of HTML text and user-written code, in the spirit of PHP templates. The user-written code is in a special-purpose scripting language that is approximately a Python subset, which runs in a hopefully-secure server-side interpreter embedded in the Python app that has limited access to system functions and resources.</P>

<p>In this document, you'll learn how to develop for infogami, including building new templates for displaying your own data, running your own copy, and developing new features and plugins.</p>


<p><a name="toc">&nbsp;</a>
   </p><div id="toc-header" style="clear: both;"><b>Table of Contents</b></div>

<table border="0" cellpadding="8" cellspacing="0" width="100%">
    <tbody><tr><td valign="top" width="50%">

<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody><tr>
        <td class="toc" colspan="3" width="100%"><b><a href="#summary">Summary (Audience Statement)</a></b></td>
    </tr><tr>
        <td class="toc" colspan="3" width="100%"><b><a href="#intro">Introduction</a></b></td>
    </tr><tr>
        <td class="toc" colspan="3"><b>Architecture</b></td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor1">1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Web Server</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor2">2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Templates</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor2.1">2.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">web.py</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor2.2">2.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">infogami</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor2.3">2.3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">OL application</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor3">3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Search</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor4">4</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Data</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc" colspan="3"><b>Template Basics</b></td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor5">5.</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Types</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor5.1">5.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Primitive Types</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor5.2">5.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Compound Types</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor6">6.</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Templates</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor6.1">6.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Type-specific Templates</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor6.2">6.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Default Templates</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor6.3">6.3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Custom Templates</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor6.4">6.4</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Useful Functions</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor7">7.</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Macros</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor7.1">7.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Best Practices</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor7.2">7.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Embedding</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
</tr></tbody></table>

<p></p></td><td valign="top" width="50%">

<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody><tr>
        <td class="toc" colspan="3"><b>WikiLanguage</b></td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor8">8</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Formatting Conventions</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor8.1">8.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Page Headers</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
   </tr><tr>
        <td class="toc-link-end"><a href="#anchor8.2">8.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Format Commands</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
   </tr><tr>
        <td class="toc-link-end"><a href="#anchor8.3">8.3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Working with Types</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
   </tr><tr>
        <td class="toc-number"><a href="#anchor9">9</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Template Syntax</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor9.1">9.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Conditionals</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
</tr><tr>
        <td class="toc-link-end"><a href="#anchor9.2">9.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Loops and Iterations</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
</tr><tr>
        <td class="toc-link-end"><a href="#anchor9.3">9.3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Regular Expressions</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc" colspan="3"><b>The Infogami API</b></td>
    </tr><tr>
        <td class="toc-number"><a href="#anchor10">10.</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Plugins</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor10.1">10.1</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Special Pages and Modes</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor10.2">10.2</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Actions</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor10.3">10.3</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Classes</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor10.4">10.4</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Decorators</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
    </tr><tr>
        <td class="toc-link-end"><a href="#anchor10.5">10.5</a>&nbsp;&nbsp;</td>
        <td class="toc" width="100%">Security Considerations</td>
        <td class="toc-link-end" align="center">&nbsp;&nbsp;</td>
<!-- </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor11"><b>Acknowledgements</b></a></td>
-->
  </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor12"><b>Authors</b></a></td>
    </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor13"><b>References</b></a></td>
    </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor14"><b>Template and Plugin Examples</b></a></td>
    </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor15"><b>Creating a new Infogami Type (step-by-step tutorial)</b></a></td>
    </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor16"><b>Code Repository</b></a></td>
    </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor17"><b>Installing the Software</b></a></td>
  <!--  </tr><tr>
        <td class="toc" colspan="3"><a href="#anchorA"><b>A.</b></a>&nbsp;&nbsp;<b>Differences From Python</b></td>        
  -->
  </tr><tr>
        <td class="toc" colspan="3"><a href="#anchor18"><b>Troubleshooting</b></a></td>        
</tr></tbody></table>

<p></p></td></tr></tbody></table>

<p><a name="summary">&nbsp;</a></p><h2>Summary (Audience Statement)</h2>

<p>
This document describes the internal workings of the Open Library
software, from a developers' point of view.  You should read it if you
are:</p>

<p><b>1)</b> a software developer wanting to add new features to Open Library.  To
do this, you will also have to be a good Python programmer experienced
in writing web server applications (not necessarily in Python).  The
document will explain the Open Library's software architecture and its
internal interfaces, and will explain how to write extensions (plugins),
but the sections about plugin writing will assume that you are familiar with Python and web programming
in general.</p>

 If you do not yet know Python, you should first study the [Python documentation](http://www.python.org/doc/) or the free book [Dive into Python](http://diveintopython.org).   Python is an easy language to learn, but the OL codebase is probably not understandable by complete beginners.
For web server principles, the somewhat dated [Philip and Alex's Guide to Web Publishing](http://philip.greenspun.com/panda) is still an informative read, though maybe someone can suggest something newer.  You should also understand the principles of software security -- see [David A Wheeler's page](http://www.dwheeler.com) for many documents.</p>

<p><b>2)</b> A user or web designer wanting to improve or customize the Open
Library's user interface, either for yourself or for our whole
community.  You will mainly want to study the section about template
programming.  You will need to know how to write HTML and it will help
if you've done some server-side template programming (such as in PHP).
It will also help if you've had some exposure to Python, but the
programming skills you'll need for template writing are generally less
intense than they'd be for extension writing.<p>

<p><b>3)</b> A general user just wanting to know how the software works behind the
scenes.  You might not understand all the details, but reading the doc
should give you a general impression of how sites like this are put
together.</p>

<p><b>4)</b> A librarian or metadata maintainer wanting to process large volumes of
metadata for import into the Open Library.  If you only want to import a few books, it's
probably easiest to use the web interface (or the Z39.50 interface once we have one).  To
import bulk data, you'll have to process it into a format that Open Library can understand,
which may require programming, but you can use your own choices of languages and
platforms for that purpose since you only have to create uploadable files, rather than
use language-specific interfaces.  You'll mainly want to look at the section about data
formats and schemas.

<p>If you just want to be an OL user accessing or editing book data, you do
NOT need to read this doc.  The doc is about how to customize and extend
the software, not how to use it.  As developers and designers, our goal
is to make the site self-explanatory for users and not need much separate
documentation, but we do have some user docs at <a href="http://openlibrary.org/help">/help</a>.
</p>

<p><a name="intro">&nbsp;</a></p><h2>Introduction</h2>

<p>Infogami is a wiki application framework built on <a href="http://webpy.org/">web.py</a>.  Actual
applications (like <a href="http://openlibrary.org/">Open Library</a>) are written by extending Infogami through two layers: plugins and templates.  
Plugins are <a href="http://python.org">Python</a> modules
that get loaded into Infogami through a special API.   They
are invoked by submitting HTTP requests to the application, either HTML
form posts or direct GET requests.  Plugins can use any library or
application code that they wish, and they create Python objects to
represent results, that then get expanded to HTML by templates.
Templates are a mixture of HTML text and user-written code,
approximately in the spirit of PHP templates<!--, but a bit less powerful -->.
The user-written code is in a special-purpose scripting language that is
approximately a Python subset, which runs in a hopefully-secure
server-side interpreter (embedded in the Python app) that has limited
access to system functions and resources.</p>


<p><a name="basics">&nbsp;</a></p><h2>&nbsp;&nbsp;Architecture</h2>

<p><a name="anchor1">&nbsp;</a><h3><a href="#toc" class="toc-link">1.</a>&nbsp;&nbsp;Web Server</h3>

<p>The <a href="http://lighttpd.net/">lighttpd</a> HTTP server runs <a href="http://infogami.org/">Infogami</a> through a FastCGI interface using <a href="http://trac.saddi.com/flup">Flup</a>.  (There can be multiple concurrent infogami instances that the lighttpd server distributes requests between, although Open Library currently just runs one.)  Infogami is written
   in <a href="http://python.org/">Python</a> (Open Library currently requires 2.5 or greater) and uses <a href="http://webpy.org/">web.py</a> and <a href="http://www.openlibrary.org/about/tech"><em>ThingDB</em></a>.  ThingDB uses <a href="http://postgresql.org/">PostgreSQL</a> as its data store. <a href="http://www.initd.org/tracker/psycopg/wiki/PsycopgTwo">Psycopg2</a> is the Python driver for PostgreSQL. Open Library uses <a href="http://cr.yp.to/daemontools/supervise.html">supervise</a> (see also <a href="http://cr.yp.to/daemontools.html">daemontools</a>) to make sure everything keeps running. <a name="origin_footnote2"></a><a href="#footnote2" class="footnote">[2]</a>
</p>

<p><a name="anchor2">&nbsp;</a><h3><a href="#toc" class="toc-link">2.</a>&nbsp;&nbsp;Templates</h3>

<p>The infogami application relies on various <em>Web templates</em> (these are code+HTML snippets).  The initial templates are static files but they get edited through the wiki interface, and new ones get added through the wiki, so the real versions live entirely in the database. 
</p>

<p><a name="anchor2.1">&nbsp;</a><h4><a href="#toc" class="toc-link">2.1</a>&nbsp;&nbsp;web.py</h4>

<p>The goal of web.py is to build the ideal way to make web apps. web.py allows you to build HTTP responses, makes the database
easier to use, and creates a templating evironment that tries to bring Python into HTML. [<a href="http://groups.google.com/group/webpy/msg/f266701d97e7ceb1">*</a>]</p>

<p><a name="anchor2.2">&nbsp;</a><h4><a href="#toc" class="toc-link">2.2</a>&nbsp;&nbsp;infogami</h4>

<p>Each infogami page (i.e. something with a URL) has an associated type. Each type contains a schema that states what fields can be used with it and what format those fields are in. Those are used to generate view and edit templates which can then be further customized as a particular type requires. </p>

<p><a name="anchor2.3">&nbsp;</a><h4><a href="#toc" class="toc-link">2.3</a>&nbsp;&nbsp;OL application</h4>

<p> <i>[ See <a href="http://openlibrary.org/dev/docs/ui">State of the UI</a> ]</i> ... <a name="origin_footnote3">&nbsp;</a><a href="#footnote3" class="footnote">[3]</a> </p>


<p><a name="anchor3">&nbsp;</a><h3><a href="#toc" class="toc-link">3.</a>&nbsp;&nbsp;Search</h3>
<p>Infogami also accepts plug-ins and Open Library uses one for the <a href="http://lucene.apache.org/solr/">Solr</a> search engine.  Solr is a JSP currently sitting in a <a href="http://www.mortbay.org/">Jetty</a> http server, so it communicates with Infogami through a local http socket.  Solr itself wraps the <a href="http://lucene.apache.org/">Lucene</a> search library.  These run under <a href="http://java.sun.com/">Java</a> (Open Library currently uses Java 1.5).  Solr is built under <a href="http://ant.apache.org/">Apache Ant</a> and has a few config and schema files, plus a startup script (solr.sh) that has to be manually edited to set the port number.  I think we currently use Lucene as a downloaded .jar file so we don't build it.
</p>

<p>The solr-infogami plugin also calls out to <em>an archive.org PHP script</em> that expands basic search queries to advanced queries.  It may also start using <em>the openlibrary.org flipbook</em> (with some possible customizations) to display OCA scans for pages containing fulltext search results.
</p>


<p><a name="anchor4">&nbsp;</a><h3><a href="#toc" class="toc-link">4.</a>&nbsp;&nbsp;Data</h3>

<p>Open Library has a bunch of catalog data and fulltext acquired from various sources, either sitting in the Archive or to be uploaded to there.  I think the acquisition processes (including web crawling scripts for some of the data) is outside the scope of an Open Library software install. There are a bunch of additional scripts to make the stuff usable in openlibrary and these need to be documented.  These include <em>TDB Conversion Scripts</em> written by dbg, and (for OCA fulltext) <em>Archive Spidering</em> and <em>Solr Importing</em> scripts written by phr.
</p>


<p><a name="basics">&nbsp;</a></p><h2>&nbsp;&nbsp;Template Basics</h2>

<p><a name="anchor5">&nbsp;</a><h3><a href="#toc" class="toc-link">5.</a>&nbsp;&nbsp;Types</h3>

<p>There are two kinds of types in infogami. <a href="#anchor5.1">Primitive types</a> and <a href="#anchor5.2">compound types.</a> Primitive types are for representing integers, strings etc.</p>

<p>Other primitive and compound types can be added by creating a page in the wiki with type type/type.
</p>
<p>Sometimes you might want to link two different types. For example, book type has an author property and you want to add a books field to the author, which contains all books where author property of the book is this author. This is achieved by adding a backreference to the author type.
</p>

<p><a name="anchor5.1">&nbsp;</a><h4><a href="#toc" class="toc-link">5.1</a>&nbsp;&nbsp;Primitive Types</h4>

<p>Available primitive types are:</p>

<p>
<b>type/int</b><br />
<b>type/boolean</b><br />
<b>type/string</b> - <i>for single line text</i><br />
<b>type/text</b> - <i>for multiline text</i><br />
</p>


<p><a name="anchor5.2">&nbsp;</a><h4><a href="#toc" class="toc-link">5.2</a>&nbsp;&nbsp;Compound Types</h4>

<p>Compound types specify what properties a thing of that type must have. Available compound types are:</p>

<p><b>type/type</b><br />
   <i>Type for representing all types. It defines the following properties:</i>
</p>
<ul>
<li>description of type type/text - description of type </li>
<li>is_multiple of type type/boolean - to distinguish between primitive and compound types</li>
<li>properties of type type/property - set of properties a thing of this type can have. This property can have multiple values.</li>
<li>backreferenes of type type/backreference - set of backreferences a thing of this type can have. This property can have multiple values. Back-references are explained later in this document.</li>
</ul>


<p><b>type/property</b><br />
   <i>Type for representing properties in a type. It defines the following properties ...</i>
</p>
<ul>
<li>name of type type/string - name of the property</li>
<li>type of type type/type - expected type of the value</li>
<li>is_unique of type type/boolean - can this type have multiple values?</li>
<li>description of type type/string - readable description of this property</li>
</ul>

<p><b>type/backreference</b><br />
   <i>later ...</i>
</p>

<p><b>type/page</b><br />
   <i>Type for wiki pages. It defines the following properties ...</i>
</p>
<ul>
<li>title of type type/string - title of the page</li>
<li>body of type type/text - body of the page</li>
</ul>


<p><b>type/template</b><br />
   <i>Type for template pages. It defines the following properties ...</i>
</p>
<ul>
<li>title of type type/string - title of the template</li>
<li>body of type type/text - body of the template</li>
</ul>




<p><a name="anchor6">&nbsp;</a><h3><a href="#toc" class="toc-link">6.</a>&nbsp;&nbsp;Templates</h3>

<p>Infogami uses templates to control the look and feel of the site. Custom templates can be provided in the wiki to enhance functionality or customize the look and feel of the site.</p>

<p>There are two kinds of templates. Regular templates and type-specific templates. Type-specific templates are used to render a wiki page based on its type.</p>

<p>Regular templates must be placed at path <a href="http://openlibrary.org/templates/">templates/</a> and end with .tmpl extension. type-specific templates must be placed at <a href="http://openlibrary.org/type/">type/</a> and end with .tmpl extension.</p>

<p>With Open Library, only site administrators can modify the templates that reside in the <a href="http://openlibrary.org/templates/">templates/</a> and <a href="http://openlibrary.org/type/">type/</a> directories. If users want to override these templates, they must create their own set of templates in their user directory, and change their template root in their user preferences. For more information, see <a href="#anchor6.3">Custom Templates.</a>

<p><a name="anchor6.1">&nbsp;</a><h4><a href="#toc" class="toc-link">6.1</a>&nbsp;&nbsp;Type-specific Templates</h4>

<p>There can be 4 type-specific templates for every type.
</p>
<ul>
 <li><b>view.tmpl</b> - Template to specify how to view a page</li>
 <li><b>edit.tmpl</b> - Template to specify how to edit a page</li>
 <li><b>repr.tmpl</b> - Template to specify how objects of this type appear when viewing pages of other types which has a property of this type.</li>
 <li><b>input.tmpl</b> - Template to specify how objects of this type appear when editing pages of other types which has a property of this type.</li>
</ul>

<p>For more information on how the repr and input templates are used, please see <a href="#anchor3.4">Useful Functions.</a></p>

<p><a name="anchor6.2">&nbsp;</a><h4><a href="#toc" class="toc-link">6.2</a>&nbsp;&nbsp;Default Templates</h4>

<p>It is not compulsory to specify all these templates for every type. When a type-specific template is not specified for a type, a default template is used. The following are the default templates:
</p>
<ul>
 <li><b>templates/default_view.tmpl</b> - <a href="http://www.openlibrary.org:8080/templates/default_view.tmpl">View Code</a> or <a href="http://www.openlibrary.org:8080/type/page">View Page Using Template</a></li>
 <li><b>templates/default_edit.tmpl</b> - <a href="http://www.openlibrary.org:8080/templates/default_edit.tmpl">View Code</a> or <a href="http://www.openlibrary.org:8080/type/page?m=edit">View Page Using Template</a></li>
 <li><b>templates/default_repr.tmpl</b> - <a href="http://www.openlibrary.org:8080/templates/default_repr.tmpl">View Code</a> </li>
 <li><b>templates/default_input.tmpl</b> - <a href="http://www.openlibrary.org:8080/templates/default_input.tmpl">View Code</a> </li>
 <li><i>Note to Anand: what about http://www.openlibrary.org:8080/templates/default_ref.tmpl ?</i></li>
</ul>
<p>There are many other interesting regular templates. Some of them are:
</p>
<ul>
 <li><b>templates/site.tmpl</b> - to specify the overall look and feel of a web site - <a href="http://www.openlibrary.org:8080/templates/site.tmpl">View Code</a> or <a href="http://www.openlibrary.org:8080/">View Page Using Template</a></li>
 <li><b>templates/diff.tmpl</b> - to display a diff between two versions of a page - <a href="http://www.openlibrary.org:8080/templates/diff.tmpl">View Code</a> or <a href="http://www.openlibrary.org:8080/dev/docs?b=13&a=12&m=diff">View Page Using Template</a></li>
 <li>...</li>
</ul>

<p><a name="anchor6.3">&nbsp;</a><h4><a href="#toc" class="toc-link">6.3</a>&nbsp;&nbsp;Custom Templates</h4>

<a href="http://www.openlibrary.org/preferences/"><img src="http://invisible.net/openlibrary/ui_files//login.png" align="right" border="0" /></a>

<p>A user can create their own set of templates by creating a subdirectory in the 'user' directory ('user/[username]'). 
A user can create a new template for each set of templates they want to override. If a template does not exist in a user's subdirectory, 
then the default set of templates will be used. Templates are created in the same manner as any new page is created in a wiki.
<!-- Please note that the default templates that exist in the 'templates' directory are only 
editable by Open Library site administrators. --></p>

<p>For purposes of illustration, we will view the contents of ('user/brewster/*')
<ul>
<li><a href="http://www.openlibrary.org/user/brewster/type">/user/brewster/type/</a></li>
<li><a href="http://www.openlibrary.org/user/brewster/templates">/user/brewster/templates/</a></li>
</ul>


<p>To view the Open Library using a set of custom templates, you must change your template preferences: </p>

<ul>
<li>Log in with your username and password</li>
<li>Click on <a href="http://www.openlibrary.org/preferences">"Preferences"</a> in the upper-right corner of the screen</li>
<li>Change your template root to "/user/[username]"</li>
</ul>

<p><i>NOTE: Changing the template root to 'user/brewster' will load the templates used <a href="http://invisible.net/openlibrary/ui_files//brewster.skin.png?keepThis=true&amp;TB_iframe=true&amp;height=599&amp;width=800" title="User-defined Template Set (click on image to return to document)" class="thickbox">in this example.</a></i></p>

<p>It is also possible to create custom Cascading Style Sheet (CSS) files and JavaScript files in the wiki. 

<p>To create a custom CSS file in the wiki, 
create a page in your user directory entitled 'user/[username]/[filename].css' and select 'rawtext' for the pagetype. Once the CSS file has been successfully created,
 it can be linked to the template using the '$add_stylesheet' command:</p>

<div class="blue">
<code class="normal">
$add_stylesheet('/static/css/search.css')
</code></div>

<p>JavaScript files can be created in the same manner, using a '.js' extension and the '$add_javascript' command:</p>

<div class="blue">
<code class="normal">
$add_javascript('/static/js/randomsearch.js')
</code></div>

<p>It is important to note that when a page with the type 'rawtext' is added to the wiki, the editing function is not readily apparent. 
To edit a rawtext page, simply add '?m=edit' to the url.</p>

<p><i>Example:</i>
<ul>
<li><a href="http://openlibrary.org/user/anand/master.css">http://openlibrary.org/user/anand/master.css</a></li>
<li><a href="http://openlibrary.org/user/anand/master.css?m=edit">http://openlibrary.org/user/anand/master.css?m=edit</a></li>
</ul>

<p><a name="anchor6.4"></a><h4><a href="#toc" class="toc-link">6.4</a>&nbsp;&nbsp;Useful Functions</h4>

<p>There are some useful functions, which are very handy in writing view and edit templates.
</p>

<ul>
<li><b>thingrepr(value, type) - </b>This calls repr template of the specified type with value as argument.</li>
<li><b>thinginput(type, name, value) - </b>This calls input template of the specified type with value, name as arguments.</li>
</ul>

<p>Lets take an example. Suppose there are many types, which need to display an image. Probably they will do that by defining a type type/image for representing images. Instead of worrying how to display and edit (upload) images, these types can just use <code>thingrepr</code> and <code>thinginput</code> macros and define <code>repr</code> and <code>input</code> templates for <code>type/image</code>. Later in future, if you want to change how to display/upload image, you don't have to change in multiple places.</p>

<p>There are some global functions, which are accessible by every template. For more information see <a href="#anchor10.4">Infogami API &gt; Decorators</a>.
</p>




<p><a name="anchor7">&nbsp;</a><h3><a href="#toc" class="toc-link">7.</a>&nbsp;&nbsp;Macros</h3>

<p>Macros are like functions in any programming language.
   Macros look very much like templates, but they can be called from wikipages and other templates and macros. 
   Macros can be written in the wiki just like templates. 
   Macros must be placed in <a href="http://www.openlibrary.org/macros/">macros/</a> path and type must be type/macro. As a convention, they are named in <code>CamelCase</code>. 
</p>

<p><a name="anchor7.1">&nbsp;</a><h4><a href="#toc" class="toc-link">7.1</a>&nbsp;&nbsp;Best Practices</h4>

<p>Macros introduce an element of modularity when designing web templates in infogami. A common practice is to use macros for any repeatable design elements. This can be as simple as an HTML callout box, or a script. For instance, the "SAVE", "PREVIEW", and "DELETE" buttons on every edit form on the Open Library site are generated by the "EditButtons" Macro code below:

<div id="form-border">
<div id="metadata-body">
{{EditButtons()}}
<br /><br />
<div class="blue">
<code class="normal">
&lt;p&gt;&lt;strong&gt;Edit summary&lt;/strong&gt; (briefly describe the changes you have made):<br />
&lt;input type="text" name="_comment" style="width: 100%" value="" /&gt;<br />
&lt;/p&gt;<br />
&lt;p&gt;<br />
&lt;button class="button" type="submit"  value="$_.SAVE"  name="_save" title="Save"&gt;&lt;img src="/static/images/save.png" alt="Save" /&gt;&lt;/button&gt;<br />
&lt;button class="button" type="submit"  value="$_.PREVIEW" name="_preview" title="Preview"&gt;&lt;img src="/static/images/preview.png" alt="Preview" /&gt;&lt;/button&gt;<br />
&lt;button class="button" type="submit"  value="$_.DELETE" name="_delete" title="Delete"&gt;&lt;img src="/static/images/delete.png" alt="delete" /&gt;&lt;/button&gt;<br />
</p>
<br /></code></div>
</div>
</div>


<p>Intelligent use of macros results in clean, readable code that can be easily understood and repurposed by other users. For instance, the <a href="http://www.openlibrary.org/type/author/view.tmpl">author view</a> template is a good example of a template with a highly modular and streamlined design. <a href="http://www.openlibrary.org:8080/a/Mark_Twain">View Page Using Template</a>


<p><a name="anchor7.2">&nbsp;</a><h4><a href="#toc" class="toc-link">7.2</a>&nbsp;&nbsp;Embedding</h4>

<p>Macros can be invoked either through the wiki interface when editing a page in Markdown, or as a script when building web templates.

<p>The syntax to call a macro from a wiki page is:
</p>
<div class="blue">
<code class="normal">{{HelloWorld()}} or {{MyMacro(&quot;arg1&quot;, &quot;arg2&quot;)}}<br />

</code></div><p>The syntax to call a macro from templates and macros is:
</p>
<div class="blue">
<code class="normal">$:macros.HelloWorld() and $:macros.MyMacro(&quot;arg1&quot;, &quot;arg2&quot;)<br />
</code></div>


<p><a name="wiki">&nbsp;</a></p><h2>&nbsp;&nbsp;WikiLanguage</h2>

<p><a name="anchor8">&nbsp;</a></p><h3><a href="#toc" class="toc-link">8</a>&nbsp;&nbsp;Formatting Conventions</h3>

<p><a name="anchor8.1">&nbsp;</a></p><h4><a href="#toc" class="toc-link">8.1</a>&nbsp;&nbsp;Page Headers</h4>

<p>The edit and view templates are defined by two lines of code that must be at the 
top of the template file in order for them to function properly (The absence of either 
of these two lines will generate an error). For instance, this example is from the 
default edition template:</p>


<div class="blue">
<code class="normal"> 
	$def with (page)<br />
<br />
	$var title: $page.title
</code></div>

<p>Additional variables can be controlled in these commands. For instance, in an edit 
template, the preview function can be disabled as follows:</p>


<div class="blue">
<code class="normal"> 
	$def with (page, preview=False )
</code></div>

<p>Display of the &lt;TITLE&gt; of the page can be constructed by making a call to a universal 
language file. For instance:</p>


<div class="blue">
<code class="normal"> 
	$var title: $_.EDIT $page.title
</code></div>

<p>would display "edit Tom Sawyer" in the edit view of an edition page by accessing the verbiage in the language file for '$_.EDIT' (edit)
 and the 'title' key in the 'edition' type [ See <a href="http://www.openlibrary.org/type/edition/">http://www.openlibrary.org/type/edition/</a>].

<p>and:</p>


<div class="blue">
<code class="normal"> 
	$var title: $_.VIEW $page.d.get('name')
</code></div>

<p>would display "View Mark Twain" when viewing an author page by accessing the 'name' 
attribute in the 'author' type [See <a href="http://openlibrary.org/type/author/">http://openlibrary.org/type/author/</a>].

<p><a name="anchor8.2">&nbsp;</a><h4><a href="#toc" class="toc-link">8.2</a>&nbsp;&nbsp;Format Commands</h4>
<p><a name="anchor8.3">&nbsp;</a><h4><a href="#toc" class="toc-link">8.3</a>&nbsp;&nbsp;Working with Types</h4>

<p>The page 'get' statements make a call to the document type to pull the corresponding 
information for display on the page. For instance the following table illustrates our 
current author type:</p>

<div id="form-border">
<div id="metadata-body">

<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tbody>

<tr>
  <td class="historyheader"><img src="/static/images/name.schema.png" alt="Name" border="0" /></td>
  <td class="historyheader"><img src="/static/images/type.schema.png" alt="Type" border="0" /></td>
</tr>

<tr>
    <td class="history">description</td>
    <td class="history">
</td>
</tr>
<tr>
    <td class="history">is_primitive</td>

    <td class="history">
</td>
</tr>
<tr>
    <td class="history">properties</td>
    <td class="history">website  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>

    <td class="history">properties</td>
    <td class="history">bio  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>
    <td class="history">properties</td>
    <td class="history">photograph  of type <a href="/type/image">type/image</a>


</td>
</tr>
<tr>
    <td class="history">properties</td>
    <td class="history">name  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>

    <td class="history">properties</td>
    <td class="history">death_date  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>
    <td class="history">properties</td>
    <td class="history">alt_names  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>
    <td class="history">properties</td>
    <td class="history">location  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>

    <td class="history">properties</td>
    <td class="history">birth_date  of type <a href="/type/string">type/string</a>


</td>
</tr>
<tr>
    <td class="history">backreferences</td>
    <td class="history">Back-reference to authors property of <a href="/type/edition">type/edition</a>


</td>
</tr>
</tbody>
</table>

</div>
</div>


<p>Therefore using this command:</p>

<div class="blue">
<code class="normal"> 
	$page.d.get('name')
</code></div>

<p>on the view template will display the author name wherever used on an author template.</p>

<p><a name="anchor9">&nbsp;</a><h3><a href="#toc" class="toc-link">9</a>&nbsp;&nbsp;Template Syntax</h3>

<p><a name="anchor9.1">&nbsp;</a><h4><a href="#toc" class="toc-link">9.1</a>&nbsp;&nbsp;Conditionals</h4>

<p>'If' statements are used in much the same manner as in other scripting languages, 
invoking an action if a certain state exists. For instance, if page preview is activated in an edit template as follows:</p>
 
<div class="blue">
<code class="normal"> 
if $def with (page, preview=True ), 
</code></div>

<p>the following command would format the HTML contents of the page 
wherever it is inserted in the edit template:</p>

<div class="blue">
<code class="normal"> 
$if preview:<br />
<br />
    &lt;p&gt;$:format(page.body)&lt;/p&gt;
</code></div>
    
<p>The 'if' statement can also be used in conjunction with the 'get' statement to hide 
empty data fields on a page. For instance:</p>

<div class="blue">
<code class="normal"> 
	$if page.d.get('language'): <br /><b>Language:</b> $page.language
</code></div>

<p>would display the language a book was published in if that data is available for that 
book, or:</p>

<div class="blue">
<code class="normal"> 
	$if page.d.get('birth_date'): $page.d.get('birth_date')&nbsp;-&nbsp;<br />
	$if page.d.get('death_date'): $page.d.get('death_date')
</code></div>

<p>would display the date of birth and date of death for a given author on the author 
view template if they exist.</p>


<p><a name="anchor9.2">&nbsp;</a><h4><a href="#toc" class="toc-link">9.2</a>&nbsp;&nbsp;Loops and Iterations</h4>
<p><a name="anchor9.3">&nbsp;</a><h4><a href="#toc" class="toc-link">9.3</a>&nbsp;&nbsp;Regular Expressions</h4>

<p><a name="api">&nbsp;</a></p><h2>&nbsp;&nbsp;The Infogami API</h2>

<p><a name="anchor10">&nbsp;</a><h3><a href="#toc" class="toc-link">10.</a>&nbsp;&nbsp;Plugins</h3>

<p>Functionality of infogami can be extended by adding new plugins to it. 
   Plugin in infogami is a python package with the following directory structure.
</p>
<ul>
 <li><b>foo/</b></li>
 <li><b>foo/__init__.py</b> - required to make foo a python package</li>
 <li><b>foo/code.py</b> - this is imported when infogami starts</li>
 <li><b>foo/templates/</b> - place to keep templates. This is optional.</li>
</ul>
<p>see <code>sample_run.py</code> in infogami repository to find out how to add a plugin to infogami.
</p>

<p><a name="anchor10.1">&nbsp;</a><h4><a href="#toc" class="toc-link">10.1</a>&nbsp;&nbsp;Special Pages and Modes</h4>

<p>A plugin can add special pages to infogami and add new modes to wiki pages. 
   Special pages are paths which are treated differently than regular wiki pages. login, logout, sitepreferences etc. are some examples of special pages. Modes are actions that be done on a wiki page. view, edit, history, diff etc. are some examples of wiki modes.
</p>
<p><code>infogami.utils.delegate</code> module provides two special classes <code>page</code> and <code>mode</code>. Any class that extends from <code>page</code>  becomes a special page with path same as the class name and any class that extends from <code>mode</code> becomes a wiki mode with name of the mode same as the class name.
</p>

An example:

<div class="blue">
<pre><code class="normal"> # hello/code.py
 class hellopage(delegate.page)
     def GET(self, site)
         return &quot;hello page!&quot

 class hello(delegate.mode)
     def GET(self, site, path)
         return &quot;hello mode for &quot; + path
</code></pre></div>

If this `hello` plugin is added to infogami, `/hellopage` page displays `hello page!` and `/foo?m=hello` displays `hello mode for foo`.

<p><a name="anchor10.2">&nbsp;</a><h4><a href="#toc" class="toc-link">10.2</a>&nbsp;&nbsp;Actions</h4>

<p>A plugin can also add new <code>actions</code> to the system. Action is a utility function, which can be invoked from the command line as shown in the following example.
</p>
<div class="blue">
<code class="normal">$ python run.py action_name arg1 arg2<br />
<br />
$ python run.py startserver 9000<br />
$ python run.py help<br />
$ python run.py movetemplates<br />
</code></div><p>The default action is <code>startserver</code> and that is invoked when no action is specified. 
</p>
<p>To convert a function in to an action, it must decorated with <code>infogami.action</code> decorator. The following is an example of action.

</p>
<div class="blue">
<code class="normal">@infogami.action<br />
def hello(name=&quot;world&quot;):<br />
    print &quot;hello, &quot; + name + &quot;!&quot;<br />
</code></div><p>Once this plugin is added to infogami, this action can be used.
</p>
<div class="blue">
<code class="normal">$ python run.py hello<br />
hello, world!<br />
$ python run.py infogami<br />
hello, infogami!<br />
</code></div><p>The <code>help</code> action prints the list of all available actions.
</p>

<p>There are some important actions, that every plugin author must know. 
</p>
<p><strong>install</strong>: The <code>install</code> action runs all the install hooks. Install hook is a function without any arguments decorated by <code>infogami.install_hook</code>. Any plugin can add a new install hook to do some actions to initialize an infogami instance. Some of the actions are install hooks too.
</p>
<p><strong>movefiles</strong>: The <code>movefiles</code> action moves all the files in <code>$plugin/files/</code> from every plugin to <code>static/</code> directory. This is also an install hook. If a plugin needs to access any static resources, they must be put in <code>files/</code> directory of that plugin. Keeping resources directly in <code>static/</code> is not a good idea and should be discouraged.

</p>
<p><strong>movetemplates</strong>: The <code>movetemplates</code> action moves templates from every plugin to wiki. Optional prefix can be specified to limit the templates that are moved into the wiki. This is also an install hook.
</p>


<p><a name="anchor10.3">&nbsp;</a><h4><a href="#toc" class="toc-link">10.3</a>&nbsp;&nbsp;Classes</h4>
<p><a name="anchor10.4">&nbsp;</a><h4><a href="#toc" class="toc-link">10.4</a>&nbsp;&nbsp;Decorators</h4>

<p>To make a function accessible in templates, that function must be decorated with <code>infogami.utils.view.public</code> decorator. 
   Since templates can be written by untrusted users, utmost care must be taken when exposing a function in templates.
</p>

<p><a name="anchor10.5">&nbsp;</a><h4><a href="#toc" class="toc-link">10.5</a>&nbsp;&nbsp;Security Considerations</h4>

<p>The basic flow is: the user submits a url or HTML form; the FCGI handler
matches the URL patch against a series of regexps to dispatch the
request to the proper plugin; the plugin receives the GET or POST data
and creates results as Python objects (e.g. a list of strings or ints);
the plugin then loads a template (designated in the plugin code) which
receives the result objects as arguments.  The template code then
expands the result to HTML which gets presented to the user's browser.
Thus, a user can "re-skin" the application by modifying the static HTML
or the script code in the templates that he or she uses.  A few initial
templates (such as the application's top-level HTML page) are included
in the application source tree, and the rest are created and edited
through the wiki interface.</p>

<p>Plugins are written by the application developers and are part of the
source code tree for the application.  Templates are entered and updated
through the wiki HTTP interface, are stored in the database just like
other wiki pages, and can be written by arbitary users.  Thus, templates
are potentially hostile and therefore require security precautions
during execution.  Templates give a flexible means of creating
presentation HTML, but for security reasons, operations requiring access
to system functions must be implemented in plugins, not templates.
Templates can be application-wide or can be specific to a given user
account.</p>




<!--
<p><a name="anchor11">&nbsp;</a></p><h2>&nbsp;&nbsp;Acknowledgements</h2>
-->

<p><a name="anchor12">&nbsp;</a></p><h2>&nbsp;&nbsp;Authors</h2>
       <p><a href="http://openlibrary.org/people/aaronsw/">aaronsw</a>,
 <a href="http://openlibrary.org/people/anand/">anand</a>,
 <a href="http://openlibrary.org/people/phr/">solrize</a> and
 <a href="http://openlibrary.org/people/webchick/">webchick</a>.</p>

<p><a name="anchor13">&nbsp;</a></p><h2>&nbsp;&nbsp;References</h2>

<table border="0" width="99%">
<tbody>
<tr><td class="author-text" valign="top"><b><a name="footnote1">&nbsp;</a><a href="#origin_footnote1" class="footnote">[1]</a></b></td>
<td class="author-text">"<a href="http://openlibrary.org/about/tech">About the technology</a>", last edited <a href="http://openlibrary.org/about/tech?m=history">August 2007.</a><br>
<span class="hyperlink">http://openlibrary.org/about/tech</span></td>
</tr>
<tr><td class="author-text" valign="top"><b><a name="footnote2">&nbsp;</a><a href="#origin_footnote2" class="footnote">[2]</a></b></td>
<td class="author-text">"<a href="http://www.openlibrary.org/about/architecture">About the architecture</a>", last edited <a href="http://www.openlibrary.org/about/architecture?m=history">August 2007.</a><br>
<span class="hyperlink">http://www.openlibrary.org/about/architecture</span></td>
</tr>
<tr><td class="author-text" valign="top"><b><a name="footnote3">&nbsp;</a><a href="#origin_footnote3" class="footnote">[3]</a></b></td>
<td class="author-text">"<a href="http://www.openlibrary.org/dev/docs/ui/">State of the UI</a>", last edited <a href="http://www.openlibrary.org/dev/docs/ui?m=history">September 2007.</a><br>
<span class="hyperlink">http://www.openlibrary.org/dev/docs/ui/</span></td>
</tr>
<tr><td class="author-text" valign="top"><b><a name="footnote4">&nbsp;</a><a href="#origin_footnote4" class="footnote">[4]</a></b></td>
<td class="author-text">"<a href="http://infogami.org/dev/quicklook">Quick Look at Infogami</a>", last edited <a href="http://infogami.org/dev/quicklook?m=history">October 2007.</a><br>
<span class="hyperlink">http://infogami.org/dev/quicklook</span></td>
</tr>
</tbody></table>



<p><a name="anchor14">&nbsp;</a></p><h2>&nbsp;&nbsp;Template and Plugin Examples</h2>

<p>The following examples illustrate what is possible with the Infogami template language.</p>

<p><img src="http://invisible.net/openlibrary/ui_files//arrow.png" alt="Disclosure Arrow"> <a href="http://www.openlibrary.org/static/docs/results.png?keepThis=true&amp;TB_iframe=true&amp;height=599&amp;width=800" title="Faceted Search example (click on image to return to document)" class="thickbox">Search Template</a><br />
<img src="http://invisible.net/openlibrary/ui_files//arrow.png" alt="Disclosure Arrow"> <a href=".png?keepThis=true&amp;TB_iframe=true&amp;height=599&amp;width=800" title="Price Check (click on image to return to document)" class="thickbox">Price Check</a> <br />
<img src="http://invisible.net/openlibrary/ui_files//arrow.png" alt="Disclosure Arrow"> <a href=".png?keepThis=true&amp;TB_iframe=true&amp;height=599&amp;width=800" title="Price Check (click on image to return to document)" class="thickbox">Data Visualization</a> </p>

<p><a name="anchor15">&nbsp;</a></p><h2>&nbsp;&nbsp;Creating a new Infogami Type (step-by-step tutorial)</h2>

<p>This <a href="https://github.com/internetarchive/openlibrary/pull/7928">PR</a> details most of the code that was implemented for the scaffolding of the <a href="https://openlibrary.org/type/tag">Tag</a> type in 2023. The following sections provide context to the steps necessary for scaffolding a new Infogami type in the Open Library.</p>

<h3>openlibrary/core/models.py</h3>
<p>To begin, you need to create a placeholder class for your type and register it as a ‘Thing’ within the Infobase, the database for Infogami types. To do so, you have to create a new class for the new Infogami type within <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/models.py#L1120-L1165"><code>core/models.py</code></a>. Within this class, you can include functionalities to interact with the new Infogami type. You then register the class as a new ‘Thing’ within the <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/models.py#L1208-L1216"><code>register_models</code></a> function. You also have to register the new Infogami type within the Open Library using the <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/models.py#L1219-L1232"><code>register_types</code></a> function. The following regex string <code>'^/<insert name of Infogami type>/[^/]*$'</code> indicates to <code>web.py</code> that URLs with the following path pattern belong to your Infogami type.</p>

<h3>openlibrary/core/schema.py + openlibrary/core/infobase_schema.sql</h3>
<p>Even though we have successfully registered a new ‘Thing’ within Infobase, we have not yet created the right database tables where new instances of this new type will live. If you are developing locally, you can add a new Infogami table group (using <code>schema.add_table_group</code>) within <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/schema.py#L18-L26/"><code>schema.py</code></a>. 
(_Note: The <code>schema.add_table_group</code> line in <code>schema.py</code> was commented out in the merged PR for the creation of Tag type because it was causing errors within the production environment that we did not encounter locally)</p>

<p>If you plan to have unique Open Library sequences for your new type, you will also have to add a new sequence to the Infobase in <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/schema.py#L18-L26"><code>schema.py</code></a> using <code>schema.add_seq('/type/<insert name of Infogami type>’, '/tags/OL%d<insert any unused alphabet>')</code>. With that, every time an instance of your new Infogami type is created and added to the table group, a new sequence (e.g. ‘OL123Z’) will also be generated. This acts as a unique key to this instance, allowing us to view it in the Open Library site via this key (e.g. <a href="openlibrary.org/works/OL18020194W">openlibrary.org/works/OL18020194W</a>).</p>

<p>With the addition of your new table group and sequence, when you run <code>docker compose up</code>, you should see SQL DDL script for your new type being generated in your terminal. Look out for it and copy the chunk of script into the <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/infobase_schema.sql"><code>infobase_schema.sql</code></a> file.</p>

<p>You will need to manually run the SQL DDL to create the new tables and sequences in your local Postgres database for Open Library. These are the commands to run the SQL DDL via terminal (assuming you already have the Open Library's docker containers running using <code>docker compose up</code>):</p>
<code class="normal">
docker compose exec db bash <br />
root@32f01e2c241d:/#  psql -Uopenlibrary <br />
openlibrary=# <i>INSERT ALL THE SQL DDL</i> <br />
</code>

<p>Here is an example of the SQL DDL that Infogami generated when we ran <code>docker compose up</code> that we then added within Postgres manually, both locally and in production:</p>
<code class="normal">
create  table  tag_boolean  ( <br />
	thing_id  int  references  thing, <br />
	key_id  int  references  property, <br />
	value  boolean, <br />
	ordering  int  default  NULL <br />
); <br />
create  index  tag_boolean_idx  ON  tag_boolean(key_id,  value); <br />
create  index  tag_boolean_thing_id_idx  ON  tag_boolean(thing_id); <br />
create  table  tag_int  ( <br />
	thing_id  int  references  thing, <br />
	key_id  int  references  property, <br />
	value  int, <br />
	ordering  int  default  NULL <br />
); <br />
create  index  tag_int_idx  ON  tag_int(key_id,  value); <br />
create  index  tag_int_thing_id_idx  ON  tag_int(thing_id); <br />
create  table  tag_ref  ( <br />
	thing_id  int  references  thing, <br />
	key_id  int  references  property, <br />
	value  int  references  thing, <br />
	ordering  int  default  NULL <br />
); <br />
create  index  tag_ref_idx  ON  tag_ref(key_id,  value); <br />
create  index  tag_ref_thing_id_idx  ON  tag_ref(thing_id); <br />
create  table  tag_str  ( <br />
	thing_id  int  references  thing, <br />
	key_id  int  references  property, <br />
	value  varchar(2048), <br />
	ordering  int  default  NULL <br />
); <br />
create  index  tag_str_idx  ON  tag_str(key_id,  value); <br />
create  index  tag_str_thing_id_idx  ON  tag_str(thing_id); <br />

CREATE  SEQUENCE  type_edition_seq; <br />
CREATE  SEQUENCE  type_author_seq; <br />
CREATE  SEQUENCE  type_work_seq; <br />
CREATE  SEQUENCE  type_publisher_seq; <br />
CREATE  SEQUENCE  type_tag_seq; <br />
</code>

<h3>openlibrary/plugins/openlibrary/types</h3>
<p>You can create a new <code>.type</code> file in this folder for your new type. This file specifies the schema that states what fields can be used with your type and what format those fields are in. Those are used to generate view and edit templates which can then be further customized as a particular type requires. For example, this is the <a href="https://openlibrary.org/type/tag/">view</a> page for Subject Tags and <a href="https://openlibrary.org/type/tag.yml/">this</a> is the YML format of its schema. Here is an example of a <a href="https://openlibrary.org/tags/OL7T.yml/">new Tag</a> we created which implements the Tag schema. You can include some basic fields such as Name and Description for now as it can be amended at a later stage.</p>

<p>Congrats, you have now successfully scaffolded a new Infogami type. Now, to create, view and edit instances of your Infogami type via the Open Library UI, you will have to create API endpoints and HTML pages.</p>

<h3>openlibrary/templates</h3>
<p>Within this folder, create a new folder to store the <code>add.html</code> file to send http POST requests via html form to create your Infogami type. You can reference other <code>add.html</code> templates implemented. The <i>name</i> and <i>value</i> fields of your HTML input elements are the key-value pairs passed in your HTTP request payload and picked up by <code>web.py</code> for further Python manipulations.</p>

<h3>openlibrary/templates/type</h3>
<p>Within this folder, create a new folder to store the <code>edit.html</code> and <code>view.html</code> files to view and edit your Infogami type. When you enter the view (e.g. <a href="https://openlibrary.org/tags/OL1T/">openlibrary.org/tags/OL1T</a>) and edit (e.g. <a href="https://openlibrary.org/tags/OL1T/edit/">openlibrary.org/tags/OL1T/edit</a>) pages of your Infogami type, <code>web.py</code> will automatically fetch the corresponding instance of your type via the sequence indicated in the URL path and pass its metadata to populate these HTML pages. If you are unsure what is the pattern of the path for your type, check <a href="https://github.com/JaydenTeoh/openlibrary/blob/32c6aeb8e16ae5c8a89f1ab41d36887cd0e5c98e/openlibrary/core/models.py#L1120-L1165/"><code>core/models.py</code></a> for the pattern you indicated in the <code>register_types</code> function.</p>

<h3>openlibrary/plugins/upstream</h3>
<p>With the HTML forms set up, you need to create a file in this folder to include the script for your API endpoints. You will need to create 2 classes, one for adding and the other for editing your Infogami type. You will need to specify GET and POST endpoint functions. As mentioned earlier, when a HTTP request is made via the HTML forms, the payload data can be accessed using <code>web.py</code> via the <code>web.input</code> function. For more details on implementing the endpoints, refer to other files in this folder.</p>

<p>That concludes all the technical implementations needed to create a new Infogami type.</p>




<p><a name="anchor16">&nbsp;</a></p><h2>&nbsp;&nbsp;Code Repository</h2>

<p>The infogami code repository can be found <a href="http://infogami.org/hg/">here.</a></p>

<p><a name="anchor17">&nbsp;</a></p><h2>&nbsp;&nbsp;Installing the Software</h2>

<p>Installation instructions can be found <a href="http://www.openlibrary.org/dev/docs/setup">here.</a></p>

<!--
<p><a name="anchorA">&nbsp;</a></p><h2>&nbsp;&nbsp;Differences From Python</h2>

<p><font color="green"><i>[ phr to write ]</i></font></p>
-->

<p><a name="anchor18">&nbsp;</a></p><h2>&nbsp;&nbsp;Troubleshooting</h2>

<p>Q. I can't change my page type when I create a new page in the wiki using my new 
   template set. Whenever I change the page type (to 'edition' instead of 'page', for 
   instance), it reverts back to the original type.
</p>
<p>A. Make sure your edit template contains the box for 'page type'. It is possible that 
   it was removed when the form was designed. The absence of this box means that the 
   template loses the type information whenever it is saved.
</p>
<p>Q. I am trying to use custom graphics using the type for my particular page template 
   set, however it generates this error:  error in processing template: AttributeError: 
   'str' object has no attribute 'png' (falling back to default template). What gives?
</p>
<p>A. Aha. You have to say ${key}.png because otherwise it thinks you want the png field 
   of the key variable (as in $page.doi).
</p>

<p>Q. Why doesn't the HTML formatting I enter in my edit template show up correctly on my 
   view template? I added carraige returns and page breaks in all the appropriate places, 
   but it runs together in one long paragraph.
</p>
<p>A. You need to use the '$:format' command to support HTML formatting. For instance, to 
   properly format the appearance of a biography on the author view page you would need 
   to add the following the script in the appropriate place on the page:
</p>
<p>$:format(page.bio)
</p>
<p>Q. My HTML code for any images I add via a page edit form displays on the view page. 
   For example, instead of a photo of Dave Eggers, I see &quot;&lt;img src=&quot;http://ia350629.us.archive.org/3/items/ol-images/daveeggers.gif&quot; align=&quot;left&quot;&gt;&quot;

</p>
<p>A. Again, you need to use:
</p>
<p>$:format(page.bio)
   instead of
   $page.bio
</p>
<p>if you want to support HTML formatting.
</p>
<p>Q. Help! My edit template for [this page] is royally hosed. I was trying to do 
   something fancy with [form layout | javascript | etc. ] and broke the edit template so 
   badly that I can't get back in and correct it.
</p>
<p>A. Use the emergency override to fall back to a very simplified template version and 
   see if you can make your corrections there: 
</p>
<div class="blue">
<code class="normal">[url]?m=edit&amp;rescue=true
</code></div>



<p><br><br><br>
</p>
title: Infogami Developer Tutorial
m: edit