Source
eagcms / docs / tutorial.rst
Tutorial
Intro
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:
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.:
wget<last-version>.zip 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.:
wget 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 main.py.sample into main.py Rename eagproject/settings.py.sample into eagproject/settings.py:
mv projects/eagcms/main.py.sample projects/eagcms/main.py mv projects/eagcms/eagproject/settings.py.sample projects/eagcms/eagproject/settings.py.sample
Run dev environment:
./dev_appserver.py projects/eagcms
Default url of backend is.
Frontend:.
More about dev environment.
Admin Interface
- Add new page to site tree
- To reorder site tree
- Page's title
- Page's type
- Page's controls
Simple web site
Creating
Go to.
Your site is empty. Go to. 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>IMAGE_2<<
Now Your site has a menu
Edit
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.
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 (and You should) 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"><Site Name></h1> </div> <div id="Footer"> Copyright (c) <Year> <Name Surname|Company's Name> </div>
You probably 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 changeable via root page ('Home Page').
Go into 'eagproject/eagtypes.py', add and register 'Home' class:
class Home(Page): footer = db.StringProperty(required=False) register.add(Home)
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"><Site Name></h1> --> <h1 id="SiteName">{{ root.title }}</h1>
And:
Result:
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 %}
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:
# settings.py: EAGCMS_TYPES = ('eagtypes',) # eagtypes.py: 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): return self.target def get_response(self, request): return HttpResponseRedirect(self.url) def get_absolute_url(self): return self.url register.add(Text, TextForm) register.add(Link)
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 interesting class because it shows some inner stuff EAG cms does to render pages.
get_link_target method returns self.target, which can be '_self' or '_blank'. Page's implementation returns '_blank'. This method is used for rendering site's menu(s).
get_absolute_url is standard 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 interesting method, because this method is responsible for returning 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 interesting 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)
I am goning to show You how to integrate Django application into EAG cms. It is advanced part of tutorial - so, I am going to rush through code without a lot of explanation.
Lets start by creating application nothing (We are in 'eagproject' dir):
mkdir nothing touch nothing/__init__.py touch nothing/views.py touch nothing/urls.py
nothing/views.py:
from django.template import RequestContext from django.shortcuts import render_to_response from eagadmin.account import admin_required @admin_required def admin(request): return render_to_response('nothing/admin.html', {}, context_instance=RequestContext(request)) def site(request): return render_to_response('nothing/site.html', {}, context_instance=RequestContext(request))
nothing/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('nothing.views', url(r'^admin/$', 'admin', name='admin'), url(r'^.*$', 'site', name='site'), )
Edit settings.py by adding nothing to applications list:
EAGCMS_TYPES = ( 'eagtypes', 'nothing', )
Edit urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^nothing/', include('nothing.urls', namespace='nothing')), # Rest of file ...
Prepare existing templates for nothing integration.
templates/eagsite/base.html:
{# ... #} <ul id="Menu"> <li class="home {% ifequal current root %}current{% endifequal %}"><a href="{{ root.get_absolute_url }}">{{ root.menu_title}} </a> {% eagsite_list_menu "main-menu" %} <li class="{% block nothing_menu %}{% endblock %}" ><a href="{% url nothing:site %}">Nothing</a> </ul> {# ... #}
templates/eagadmin/base.html:
<ul id="TopMenu"> <li class="{% block menu_sitetree %}{% endblock %}"> <a href="{% url eagadmin:index %}">{% trans "Site Tree" %}</a> </li> <li class="{% block menu_nothing %}{% endblock %}"> <a href="{% url nothing:admin %}">{% trans "Nothing" %}</a> </li> </ul>
Now You can create templates for Your new django's application:
mkdir templates/nothing touch templates/nothing/site.html touch templates/nothing/admin.html
templates/nothing/site.html:
{% extends "eagsite/base.html" %} {% block nothing_menu %}current{% endblock %} {% block content %} Nothing here... {% endblock %}
templates/nothing/admin.html:
{% extends "eagadmin/base.html" %} {% block menu_nothing %}active{% endblock %} {% block content %}Nothing here...{% endblock %}
And finnaly You have application 'nothing' who does nothing:
