The w20e.pycms CMS!
-------------------

Only fools and nerds create their own CMS nowadays. Hurray! Anyway, so
here it is, w20e.pycms. Using the Pyramid framework as its base,
building on top of good old Zope (and some Plone) concepts. The CMS is
created using these main ideas:

* ZODB as database
* ZCML as configuration/glue language
* small core
* optional components (like search, catalog, sharing); just include what
  you like

The CMS is a framework, not an out of the box app. What you'll need to
do is create your own Pyramid app, using the CMS as base. We've tried
to make this as easy as possible: use w20e.pycms.skeleton (to be found
on github) to obtain a paster template for your app. Run it, and there
you go...


Getting started
=====================

We assume that you know how to use buildout, create virtual
environments, like to use paster, etc. But this is only one way to get
things going...

- Create a package for your project, requiring:

  w20e.pycms

The easiest way to do so, is using our paster template
pycms_project. Install the w20e.pycms.sitemaker package (get it from
github), something along these lines:

  # virtualenv <env>
  # cd <env>; ./bin/activate
  # ./bin/easy_install w20e.pycms.sitemaker
  # paster create -t pycms_project <package name>


- Create a buildout and virtualenv for your stuff. Why not use the
  ini files and buildout files we provide in the skel directory here?

  # paster create -t pycms_buildout <same package name!>
  #
  # python bootstrap.py
  # ./bin/buildout -v -c buildout-dvl.cfg

At this stage you may want to drink a nice cuppa, read a book, etc.

- Add the default management and public css / js files (if you want):

 add this to your configure.zcml:

 <include package="w20e.pycms" file="public_resources.zcml"/>
 <include package="w20e.pycms" file="manage_resources.zcml"/>

- Include any other CSS and JS you like, using the pycms zcml directives:

  <pycms:css
    cssfile="your.css"
    csstarget="public"
    media="screen"
    />

  <pycms:js
    jsfile="your.js"
    jstarget="public"
    />

- Override assets like logo and favicon:

  <asset
    to_override="w20e.pycms:static/favicon.png"
    override_with="yourapp:static/favicon.png.png"
    />

- Most likely you'll want to override the 'content' macro, that is
  called to display a page. To do this, make your own pt file, make
  that extend 'main.macros['master'], and let it fill the 'body' slot:

<metal:define-macro define-macro="master"
                    metal:extend-macro="main.macros['master']">

  <html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="en"
      i18n:domain="w20e"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      metal:use-macro="main.macros['master']"
      >

    <head/>

    <body metal:fill-slot="body">
      Good morning Grommit...
    </body>
  </html>
  </metal:define-macro>

and add to your configure.zcml (always assuming you called your macro
main.pt):

  <pycms:macro
     name="body"
     ptfile="yourpackage:templates/main.pt"
     />


Using the CMS: core concepts
============================

The core CMS consists solely of pages. Pages are composites, that is,
pages can be arbitrarily complex and consist of 'blocks'. A block can
be anything that can be displayed: rich text, a snippet, an image,
etc.


Actions
=======

You can register actions with your content. The currently used setup
mainly uses 'perspectives' or ways to look at your content. In the
management interface these are rendered as 'tabs'. Actions are
configured using zcml. Use the action statment as follows:

<pycms:action
  name="users"
  target="./users"
  category="perspective"
  ctype="site"
/>

ctype is an optional filter.


Content types
=============

Create your own content types if you wish. You can register an icon,
and possible subtypes with your type using:

  <pycms:ctype
     name="your_type_id"
     factory=".models.yourtype.YourType"
     subtypes="someothertype,someevenothertype"
     icon="/static/img/yourtype_icon.png"
     />

Your actual model should extend either
  w20e.pycms.models.base.BaseContent
or
  w20e.pycms.models.base.BaseFolder.

You may want to use w20e.forms (read: should) for your model. Create
an xml form that describes your model, and add it. A simple model
looks like this:

from w20e.pycms.models.base import BaseContent


class SomethingSimple(BaseContent):

    """ Well, actually it's more like an 'object'... """

    add_form = edit_form = "../quote/somethingsimple.xml"

    def __init__(self, content_id, data=None):

        BaseContent.__init__(self, content_id, data)


    def base_id(self):

        return self.__data__['title']


    @property
    def title(self):

        return self.__data__['title']




robots.txt
=========
The default robots.txt disallows all. Override as per your liking...


Search
======
Would you like search enabled for your site?

Add this to your configure.zcml:

  <include package="w20e.pycms" file="search.zcml"/>


Sharing anyone?
===============
Would you like search enabled for your site?

Add this to your configure.zcml:

  <include package="w20e.pycms" file="search.zcml"/>


Settings
========
pycms.acl.force_new = True|False
        Force new version of ACL. All your security data will be lost
pycms.catalog.force_new = True|False
        Force new version of catalog. All your entries will be lost, but you
        can just run reindex-catalog and all is well again...
pycms.admin_user = <user>:<pwd>
        Admin user and password, like so: pycms.admin_user = admin:pipo
pycms.admin_secret = <somesecret>
        This secret may be used as URL parameter to obtain admin permission
        Use it wisely!
pycms.minify_css = True|False
        Minify CSS. Defaults to False
pycms.minify_js = True|False
        Minify JS. Defaults to False
pycms.logged_in_redirect = <url>
pycms.rootclass = <full dotted classname>
        Defaults to w20e.pycms.models.site.Site
pycms.roottitle = <string>
        Defaults to "Welcome"
pycms.from_addr
        Send email as ...
pycms.bcc_addr
        Send also to bcc
pycms.after_add_redirect
        Where to go after successfull add
pycms.cancel_add_redirect
        Where to go after cancelled add
pycms.after_del_redirect
        Where to go after delete
