Open source cms for mobile and desktop websites

CMS - Customizing

Styling the website

The default design is quite simple and can be changed in many aspects with css. The easiest way to start is to change the existing css files to your liking.

The default installation already extends the website’s design for customization. The directory structure contains the following directories:


The default installation is based on the python package nive_cms_design_bs3.

Static files

All files inside the static directory and subdirectories are served as static files by the webserver. Open styles.css in your css or text editor, change something and reload the website in your browser to see changes you’ve just made.

Additional images for styling (like background images) can be copied into the myWebsite/static/imgs directory and linked in the css file. (The imgs folder is technically not necessary, but Nive enables you to work with subdirectories.)

layout.css contains the website layout styles, whereas styles.css contains the styles used by page elements.

The files included in myWebsite/static are a copy of the original design included in nive_cms_design_bs3:static. If you want to recover the original design replace the contents of myWebsite/static with nive_cms_design_bs3:static.

The html code is not generated by templates contained in the static directory. If you add a template here, it will be returned as text without being rendered.


The directory myWebsite/templates contains templates, that can be customized as replacement for the default templates in nive_cms_design_bs3:templates. If myWebsite/templates is empty the website uses all default templates.

An existing myWebsite/templates/ means the website uses its own main template.

Templates are explained in detail on the next page.


The configuration of the website including database and data directory is included in


The block responsible for the design configuration contains the following code:

design = ViewModuleConf("nive_cms_design_bs3",

# add a new static directory for customized and new asset files
static = ViewModuleConf(
    id = "extended",

To switch to another design replace the default design package with the new package name e.g.:

design = ViewModuleConf("nive_cms_design_bs_grayscale", # instead of "nive_cms_design_bs3"

You just have to make sure to use the tmeplates and css provided by the new design for customization. Means the template and style files in myWebsite/templates and myWebsite/static have to be replaced.

Bootstrap CSS framework

The default design is based on the Twitter Bootstrap CSS Framework. Design definitions are neatly integrated into elements and can, at least in parts, be assigned in forms.

Please refer to the bootstrap documentation at <>

Supported features (Of course you can assign any class definitions manually):

  • Grid system and fluid grid system: Can be changed in the main template
  • Column span and offset: Accessible in the box element’s form
  • Responsive design: Also accessible in the box element’s form
  • Buttons: Links can be displayed as buttons. Accessible in the link element’s form.
  • Thumbnails: A box can be marked as image gallery and included images are rendered in the appropriate layout and sizes

Changing the styles is quite easy: The bootstrap website offers a tool change colors and grid sizes through a web form. Additional changes can be applied locally in the appropriate css file in the static directory.

Using templates

The default Nive design uses Chameleon page templates to generate html code. Please refer to the Chameleon documetation for details. Here is just a short overview.

Chameleon templates - in short


Page templates will check for valid html syntax and blocks. In case of errors the template won’t render.

All programming is included in html attributes with tal: or metal: prefix. Additionally you can use ${...} to insert values anywhere in the template. The expressions used by default in all statements are Python.

A few examples:

Inserting values (each of these examples will insert the id or title into the web page):

<div tal:content=""></div>

<span tal:replace="structure context.GetTitle()" />


Inserting html tag attributes:

<span tal:attributes="id" />

Repeating elements:

<div tal:repeat="parent context.GetParents()"

Conditional inserting:

<span tal:condition="context.GetParent()"
      tal:replace="structure" />
Statement Description
tal:define Define variables.
tal:switch Define a switch condition
tal:condition Include element only if expression is true.
tal:repeat Repeat an element.
tal:case Include element only if expression is equal to parent switch.
tal:content Substitute the content of an element.
tal:replace Replace the element with dynamic content.
tal:omit-tag Omit the element tags, leaving only the inner content.
tal:attributes Dynamically change or insert element attributes.
tal:on-error Substitute the content of an element if processing fails.

Additionally Chameleon templates also support macros and internationalisation.

Refer to the Chameleon website for a complete reference.

Templates used by the design


You have to restart the server if you change the location of a template!

If you modify the contents of a template a restart is not necessary!

The main template is stored in the website directory as:


All object templates are included in If you need to change one of the existing templates, copy it to website/templates/. Restart the server. The copy will automatically be found and used from it’s new location.

The files included in website/templates are a copy of the original design included in In fact the design in your websites extends the original design by using it’s own directory for templates. (This is configured in website/

The main template

You may open website/templates/ to see what the main template looks like. It contains the html header, body and content area. The template itself is loaded as macro in the context of pages and renders the websites scaffold.

The template contains two places where page elements are inserted:

  • the main content block

    <span tal:repeat="el context.GetPageElements()"
          tal:replace="structure view.RenderView(el)"/>
  • the column (in fact it is used as footer by default)

    <span tal:define="column context.GetColumn('right')"
          tal:replace="structure view.RenderView(column)"/>

The main template includes statements to generate the necessary html code for the edit mode. These statements are only executed if the page is in fact displayed in edit mode. All together only four statements are required to load all necessary ressources and markup to edit a page:

  1. Javascript and css includes in the <head>

    <tal:block tal:condition="cmsview">
      <span tal:replace="structure cmsview.EditorAssets(ignore=['jquery.js'])"/>
  2. The edit bar attached to the main content area (by default below):

    <!-- inserts page edit bar -->
    <div tal:condition="cmsview"
         tal:replace="structure cmsview.editBlockPage()" id="nive-page-edit" />
  3. The column edit bar. This is optional and depends on the design, may be included as often as required:

    <!-- inserts column edit bar -->
    <div tal:condition="cmsview"
         tal:replace="structure cmsview.editBlockColumn(name=u'footer')"
         id="nive-column-edit-footer" />
  4. The toolbox and widgets at the end of the main template:

    <!-- inserts toolbox and other cms widgets -->
    <span tal:condition="cmsview"
          tal:replace="structure cmsview.cms()" />

Object templates

Object templates use by default the object type as name.

The text element ( for example is quite simple and contains only a few lines:

<div class="pageelement peText" id="nive-element${context.GetID()}">
  <span tal:replace="structure"/>

The class=pageelement and id=pe123 attributes of the element are required for the edit mode to use the element. (123 is the id of the object.)

Context variables used in templates

Templates have most necessary variables directly accessible in statements.


context is the corresponding object the template is called for. A page will have the page object about to be rendered passed as context to the template. The same goes for text elements and any other. The context provides the objects functionality and data.

See api/page for supported functions.


In fact view contains a lot of helper functions to generate urls, access the authenticated user, get request form values or render data.

See api/view for supported functions.

Technically view is a class called by Pyramid to render the object. Instead of calling the object directly views are called with the object as context. This keeps object and rendering functionality apart and helps to add security settings.


The request contains all information about the current browser request.

See pyramid.request for details.


cmsview contains the cms editor view if active. In public mode it is None. This signals if edit mode is active.

Inserting URLs

The view variable contains functions to generate urls. (API api/view)

Static urls

To reference files in the static directory of the website use view.StaticUrl('...'). For example to get the url for an image stored in the static directoy use

<img tal:attributes="src view.StaticUrl('static/imgs/logo.png')" />

Page urls

To get the url for the current page use view.PageUrl(). This will also work if the context object is a page element and not the page itself. This will also append the file extension (.html)

<a tal:attributes="href view.PageUrl()">Link</a>

To get the url for another page pass the page object as parameter

<a tal:attributes="href view.PageUrl(resource=another_page)">Link</a>

Object urls

To get the url for the current object, use view.Url()

<a tal:attributes="href view.Url()">Link</a>

To get the url for another object pass the object as parameter

<a tal:attributes="href view.Url(resource=another_object)">Link</a>

Object urls as folder

Sometimes you may need the url to a container object without extension. In this case, use view.FolderUrl()

<div tal:define="baseUrl view.FolderUrl()"> </div>

Object file downloads

To get the download url for a file, use view.FileUrl(fieldID)

<a tal:attributes="href view.FileUrl('file')">Download</a>

All functions also take resource as optional parameter. If given, the resource will be used as object to generate the url for.

Accessing object data and functions

The context variable is the current object to be rendered. You can easily access object data and functions and use them in your templates.

To insert data you only have to know the field names the object uses. And you need to know the meta fields used by nive (meta fields are the same for all objects).

The object provides its data through the following attributes:

  • data: data fields. These are different for each object type.
  • meta: mainly system fields. These are the same for all object types. (title and id for example are stored as meta fields.)
  • files: files stored for an object. Returns a readable file object with file information.
<h1 tal:content="structure context.meta.get('title')"></h1>

<p tal:content="structure'text')"></p>

<p tal:content="context.files.get('file').size"></p>

Object functions can be called like any other Python functions. You just have to know their name and parameters. For easy handling in templates Nive objects provide many functions.

<div tal:define="parent context.GetParent()"> </div>
  • See api/pageelement for a full list of page element functions.
  • See api/pageelementcontainer for a full list of element container functions.
  • See api/page for a full list of page functions.
  • See api/root for a full list of root functions.

Mako and Jinja

The cms uses pyramids rendering capabilities. Though the default design includes Chameleon templates you can also use Mako or Jinja as template engine. The template engine to be used is selected by the file extension of the template file.

Template files are linked in each object’s configuration as template.

Content elements

Connecting element templates with the editor


require class attributes class="pageelement" id="nive-element123" in the outer html block.

<div class="pageelement " id="nive-element${context.GetID()}">


need to be defined in the main template like

<span tal:define="column context.GetPage().GetColumn(u'left')"
      tal:replace="structure view.RenderView(column)"/>

and in the column itself

<div tal:attributes="class string:pageelement peColumn; id string:nive-element${context.GetID()}">


page links by default the main template as macro

<tal:block metal:use-macro="view.index_tmpl().macros['main']">
  <tal:block metal:fill-slot="content">
    <h1 tal:content="structure'header')"></h1>
    <span tal:repeat="el context.GetPageElements(user=view.User(), checkPermissions=True)"
          tal:replace="structure view.RenderView(el, secure=True, raiseUnauthorized=False)"/>

Main template

required asset includes

<span tal:condition="cmsview"
      tal:replace="structure cmsview.EditorAssets(ignore=['jquery.js'])" />

bottom of each column

<div tal:condition="cmsview"
     tal:replace="structure cmsview.editBlockColumn(name=u'footer')"  id="nive-column-edit-footer" />

bottom of the content area

<div tal:condition="cmsview"
     tal:replace="structure cmsview.editBlockPage()" id="nive-page-edit" />

general includes for editing: inserts toolbox and other cms widgets

<span tal:condition="cmsview"
      tal:replace="structure cmsview.cms()" />
© 2013 Nive GmbH