eagcms / docs / tutorial.rst



EAG cms is as simple as possible CMS for Google App Engine (GAE) and Django

EAG cms is made using these technologies: Google App Engine and Django. So, I highly recommend You to read their documentation (and tutorials) first:

Google App Engine Docs

Django Docs

Getting started

EAG cms completely depends from GAE. So, only way to publish something created with it is through GAE. This means that You will be creating GAE application - nothing less, nothing more.

Now we do not need to publish (And You can find that topic in GAE documentation) - we need to test something in localhost. At least I am thinking You want to do that...

Prepare dev environment

All commands are tested in Linux OS only. I am sorry, but I can not make instructions for Windows and/or Mac OS users - I do not have these OS's. On the other hand, these OS's have GUI tools. So, use my instruction, these tools and common sense and I think You will do just fine.

Download GAE SDK, unzip it and enter newly created directory.:

unzip google_appengine_<last-version>.zip
cd google_appengine/

You can skip Django installation step if You have installed it already. But (It is important!!!) You need 1.1.* Django's version.

Download Django 1.1.*, untar it and make it local library for GAE SDK.:

tar zxf Django-1.1.1.tar.gz
mv Django-1.1.1/django/ ./
rm -r Django-1.1.1

Download EAG cms, untar it into projects/eagcms directory.:

mkdir -p projects
wget TODO
tar zxf TODO projects/eagcms

Rename into Rename eagproject/ into eagproject/

mv projects/eagcms/ projects/eagcms/
mv projects/eagcms/eagproject/ projects/eagcms/eagproject/

Run dev environment:

./ projects/eagcms

Default url of backend is http://localhost:8080/admin/.

Frontend: http://localhost:8080/.

More about dev environment.

Admin Interface
  1. Add new page to site tree
  2. To reorder site tree
  3. Page's title
  4. Page's type
  5. Page's controls

Simple web site


Go to http://localhost:8080/.

TODO: pic

Your site is empty. Go to http://localhost:8080/admin/. and add three pages:

  • 'Main Menu' with top = 'Home Page', title = 'Main Menu', slug = 'main-menu', type = 'Menu'
  • 'Foo' with top = 'Main Menu', title = 'Foo', slug = 'foo', type = 'Text'
  • 'Bar' with top = 'Main Menu', title = 'Bar', slug = 'bar', type = 'Text'

TODO: pic

Now Your site has a menu

TODO: pics


In admin, edit page 'Foo'. When editing You can see more fields than You were able when You were creating that page. It is because now page has type (Text) and nows that text can have 'content'.

Enter some stupid (Example: 'foo foo foo') text to Foo's content.

TODO: pics

Types' templates

Each page' type may have it's own template, which is rendered when you enter that page in frontend.

Just take a look at 'templates/eagsite/':

tree templates/eagsite/

# templates/eagsite/
# |-- base.html
# |-- page.html
# `-- types
#     `-- text.html

This is templates where You can customize Your site's look and feel. 'types' are folder where You can put custom types' templates. Take a look at text.html:

{% extends "eagsite/page.html" %}
{% block custom %}
<div class="text">{{ current.content|safe }}</div>
{% endblock %}

It simple extends page.html template and outputs page's content var. Each type may have template. If now template is pressed than system falls back to page.html template. So, that one must be presented.

'Home' type

Now You are going to create Your own page type - 'Home' type.

Take a look at 'base.html':

{% eagsite_get_page "" as root %}
<div id="Wrapper">
    {# ... #}
    <h1 id="SiteName">&lt;Site Name&gt;</h1>
<div id="Footer">
  Copyright (c) &lt;Year&gt; &lt;Name Surname|Company's Name&gt;

You probrabably can replace 'Site Name' and copyright by hand in template because there is almost zero change they are going to change. But now We are learning stuff and You are going to learn how to make these fields changanble via root page ('Home Page').

Go into 'eagproject/', add and register 'Home' class:

class Home(Page):
    footer = db.StringProperty(required=False)


Now go to admin and change 'Home Page' type to 'Home'. Edit 'Home Page' and change title to 'My Site' and footer to 'Copyright by Me'.

We are going to use it's title as site's name and footer as footer.

Go to 'base.html' and change:

<h1 id="SiteName">&lt;Site Name&gt;</h1> --> <h1 id="SiteName">{{ root.title }}</h1>


Copyright (c) &lt;Year&gt; &lt;Name Surname|Company's Name&gt; --> {{ root.footer }}


TODO: pic

Ok, that double mention of 'My site' is a little bit annoying. So, let's change it.

Create 'templates/eagsite/types/home.html':

{% extends "eagsite/base.html" %}
{% block content %}
<h1 style="text-align: center;">Welcome!!!</h1>
{% endblock %}

TODO: pic

That's better.

EAG Types concept

Site tree consist of :ref:`Page <class-page>` objects (direct or subclasses). Page is subclass of GAE PolyModel class. So all Page's subclasses are PolyModels too. Each Page object has top and order params - these two are enough to calculate order of each node in site tree.

Page class specifies some common attributes (:ref:`more details <class-page>`), but "real" data attributes must be specified by project. This is done by using EAGCMS_TYPES settings option and :ref:`register <object-register>` object:

EAGCMS_TYPES = ('eagtypes',)

from eagadmin.types import register
from google.appengine.ext import db
from eagadmin.forms import SemiWYSIWYGWidget
from django.http import HttpResponseRedirect
from django import forms

class Text(Page):
    content = db.TextProperty(required=False)

class TextForm(forms.Form):
    content = forms.CharField(widget=SemiWYSIWYGWidget)

class Link(Page):
    url = db.StringProperty()
    target = db.StringProperty(choices=['_self', '_blank'])

    def get_link_target(self):

    def get_response(self, request):
        return HttpResponseRedirect(self.url)

    def get_absolute_url(self):
        return self.url

register.add(Text, TextForm)

This code sample registers two page types: Text and Link.

First: Text classes objects will have content field. Default TextProperty's fields objects are rendering using simple textarea. If You do not want that and want to have WYSIWYG editor to enter HTML content You can create django.forms.Form subclass, make content field's widget as SemiWYSIWYGWidget (or WYSIWYGWidget) and pass it as second param to registers.add method.

Second: Link. It is more intresting class becauses it shows some inner stuff EAG cms does to render pages.

get_link_target method returns, wich can be '_self' or '_blank'. Page's implementation returns '_blank'. This method is used for rendering site's menu(s).

get_absolute_url is standart django's way of returning models' urls. The only different - it is not django's ORM model, it is GAE model object.

get_response. It is really intresting method, because this method is responsible for returting response of a Page. So if You enter page's url page itself renders content. It is small violation of MVC pattern, but it lets you to define intrenting Page types (Link for example).

Section below talks about real Page's get_response implementation.

Customizing look and feel

So, if you do not change Page's subclasses default get_response implementation, each page would be rendered using this algorithm:

  • Template var current is set to current page
  • Template var breadcrumb is set to list of page's breadcrumb
  • Template 'eagsite/types/<class-name-lowercase.html is rendered using those vars
  • If such template does not exists - template 'eagsite/page.html' is rendered

So site at least must have 'eagsite/page.html' template. It simple django template - you must edit it (and/or 'eagsite/types/*.html') to change Yours applications look and feel.

Fictional Django app integration (Advanced topic)