A Winning combination: Plone and your favorite web framework
Why?
Plone is the best CMS that is NOT written in PHP
Plone has lots of great features Easy to use and install Standards and accessibility compliant Best security track record of any major CMS Available in more than 40 languages Workflow capabilities and rules engine Versioning, history and reverting content And, of course...
Python
but...
Plone is complex
Plone can be slow
Caching is not always the answer to traffic
Plone is NOT a general web development framework But sometimes we forget that... Or clients push us to add features “We want Plone, only take this out and add a couple of features” Or we simply don't think we have an option So, we end up with...
Frankenplone
It doesn't have to be like this. You can work with your favorite tools.
Content Mirror by   Kapil Thangavelu
Content Mirror serializes Plone content into a relational database Out of the Box support for Default Plone Content Types and all built-in Archetypes Fields. Supports Any 3rd Party / Custom Archetypes Content.  Supports Capturing Containment / Content hierarchy in the serialized database.  Completely Automated Mirroring, zero configuration required beyond installation.  Support for Plone 2.5, 3.0, and 3.1
It's simple
Now we can: Use Plone only to manage content Use whatever framework we like to work with the content Take Plone out of the deployment plans Stop worrying about how to do something in terms of Plone and instead think about what we want to accomplish Simplify, simplify
And we can serve Plone content fast!
How does it work? Integrates into Plone's event stream and subscribes to content lifecycle events (object added, edited, deleted). Transform Plone content schemas into relational tables, using SQLAlchemy. All objects get a default content schema, including files and relations. Each Plone content type gets its own table.
 
Installation Download:  http://code.google.com/p/contentmirror/downloads/list Install Configure database Configure custom content types Generate tables Bulk load pre-existing content
Configure the database with ZCML <configure xmlns=&quot;http://namespaces.zope.org/zope&quot; xmlns:db=&quot;http://namespaces.objectrealms.net/rdb&quot; xmlns:ore=&quot;http://namespaces.objectrealms.net/mirror&quot;> <!-- setup a database connection --> <db:engine url=&quot;postgres://localhost/plone&quot; name=&quot;mirror-db&quot; echo=&quot;True&quot;/> <!-- associate the database connection to mirror db structures --> <db:bind engine=&quot;mirror-db&quot; metadata=&quot;ore.contentmirror.schema.metadata&quot; /> </configure>
Configure custom content types For each custom content type installed on the site: <ore:mirror content= &quot;Products.ATContentTypes.content.document.ATDocument&quot; />
Generate tables and upload content dropdb plone createdb plone --encoding=UTF-8 # generate table definitions and create tables bin/instance run parts/productdistros/ContentMirror/ddl.py postgres > mirror.sql psql plone < /home/andy/plone/zinstance/mirror.sql # optionally, load existing content bin/instance run parts/productdistros/ContentMirror/bulk.py Plone
That's it. We're ready to rock & roll
The changes are sent synchronously to the database plone# select content_id, id, title from content where id = 'front-page'; content_id |  id  |  title ------------+------------+---------------- 8 | front-page | Content Mirror sent this (1 row)
What kind of sites can take advantage of this strategy? Sites with a small number of content managers and a large number of users. Which can clearly separate content management and presentation. Magazines Newspapers Government  Non-profits
Repoze.BFG front end class WebSite(UserDict): implements(IWebSite,ILocation) __acl__ = [ (Allow, Everyone, 'view') ] def __init__(self, website_id): UserDict.__init__(self) self.__name__ = None self.__parent__ = None self.website_id = website_id session = Session() website =  session.query( PloneContent ).with_polymorphic(  PloneWebSite ).filter( PloneContent.id==website_id ).first() self.title = website.title
Plango, by Andy McKay from django.db import models from django.contrib.contenttypes.models import ContentType from utils import normalize_name class Content(models.Model): class Meta: db_table = u'content' content_id = models.IntegerField(primary_key=True, editable=False) id = models.CharField(max_length=256, editable=False) uid = models.CharField(unique=True, max_length=36, editable=False) portal_type = models.CharField(max_length=64, editable=False) status = models.CharField(max_length=64, editable=False, null=False) type = models.CharField(max_length=64, editable=False) container = models.ForeignKey('self', related_name=&quot;parent&quot;, editable=False)
Anyone? Turbogears Pylons Werkzeug Anything goes!
Content Mirror is easily extended How about? Reporting against the content Audits of changes Export to formats like JSON Other storage backends Content mirror Uses the Zope Component Architecture We can easily plug in something other than a relational database
By the way, don't worry about the Component Architecture. We have studied the Zope CA so you don't have to.
A Google App Engine frontend Take advantage of Google's infrastructure Use their user authentication facilities Let them worry about scaling Of course, kinds of sites are limited, due to GAE's strict quotas More like a toy, but shows what can be possible using Content Mirror with Plone
GAE front end application import os import wsgiref.handlers from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext import db from google.appengine.ext.db import polymodel from google.appengine.api import users class PloneContent(polymodel.PolyModel): id = db.StringProperty() uid = db.StringProperty() portal_type = db.StringProperty() status = db.StringProperty() type = db.StringProperty()
Plone content in GAE
All discussed front ends will be made available during the sprints. Keep an eye on: http://contentmirror.googlecode.com/
Case study The Library of Congress in Chile
Create multiple sites in one instance
Select content from a shared store
Define a unique site layout and style
Deploy sites using repoze.bfg
Let Plone be a part of the Python universe
Thank you! Carlos de la Guardia email:  [email_address] twitter: cguardia blog: http://blog.delaguardia.com.mx

A winning combination: Plone as CMS and your favorite Python web framework as front end

  • 1.
    A Winning combination:Plone and your favorite web framework
  • 2.
  • 3.
    Plone is thebest CMS that is NOT written in PHP
  • 4.
    Plone has lotsof great features Easy to use and install Standards and accessibility compliant Best security track record of any major CMS Available in more than 40 languages Workflow capabilities and rules engine Versioning, history and reverting content And, of course...
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    Caching is notalways the answer to traffic
  • 10.
    Plone is NOTa general web development framework But sometimes we forget that... Or clients push us to add features “We want Plone, only take this out and add a couple of features” Or we simply don't think we have an option So, we end up with...
  • 11.
  • 12.
    It doesn't haveto be like this. You can work with your favorite tools.
  • 13.
    Content Mirror by Kapil Thangavelu
  • 14.
    Content Mirror serializesPlone content into a relational database Out of the Box support for Default Plone Content Types and all built-in Archetypes Fields. Supports Any 3rd Party / Custom Archetypes Content. Supports Capturing Containment / Content hierarchy in the serialized database. Completely Automated Mirroring, zero configuration required beyond installation. Support for Plone 2.5, 3.0, and 3.1
  • 15.
  • 16.
    Now we can:Use Plone only to manage content Use whatever framework we like to work with the content Take Plone out of the deployment plans Stop worrying about how to do something in terms of Plone and instead think about what we want to accomplish Simplify, simplify
  • 17.
    And we canserve Plone content fast!
  • 18.
    How does itwork? Integrates into Plone's event stream and subscribes to content lifecycle events (object added, edited, deleted). Transform Plone content schemas into relational tables, using SQLAlchemy. All objects get a default content schema, including files and relations. Each Plone content type gets its own table.
  • 19.
  • 20.
    Installation Download: http://code.google.com/p/contentmirror/downloads/list Install Configure database Configure custom content types Generate tables Bulk load pre-existing content
  • 21.
    Configure the databasewith ZCML <configure xmlns=&quot;http://namespaces.zope.org/zope&quot; xmlns:db=&quot;http://namespaces.objectrealms.net/rdb&quot; xmlns:ore=&quot;http://namespaces.objectrealms.net/mirror&quot;> <!-- setup a database connection --> <db:engine url=&quot;postgres://localhost/plone&quot; name=&quot;mirror-db&quot; echo=&quot;True&quot;/> <!-- associate the database connection to mirror db structures --> <db:bind engine=&quot;mirror-db&quot; metadata=&quot;ore.contentmirror.schema.metadata&quot; /> </configure>
  • 22.
    Configure custom contenttypes For each custom content type installed on the site: <ore:mirror content= &quot;Products.ATContentTypes.content.document.ATDocument&quot; />
  • 23.
    Generate tables andupload content dropdb plone createdb plone --encoding=UTF-8 # generate table definitions and create tables bin/instance run parts/productdistros/ContentMirror/ddl.py postgres > mirror.sql psql plone < /home/andy/plone/zinstance/mirror.sql # optionally, load existing content bin/instance run parts/productdistros/ContentMirror/bulk.py Plone
  • 24.
    That's it. We'reready to rock & roll
  • 25.
    The changes aresent synchronously to the database plone# select content_id, id, title from content where id = 'front-page'; content_id | id | title ------------+------------+---------------- 8 | front-page | Content Mirror sent this (1 row)
  • 26.
    What kind ofsites can take advantage of this strategy? Sites with a small number of content managers and a large number of users. Which can clearly separate content management and presentation. Magazines Newspapers Government Non-profits
  • 27.
    Repoze.BFG front endclass WebSite(UserDict): implements(IWebSite,ILocation) __acl__ = [ (Allow, Everyone, 'view') ] def __init__(self, website_id): UserDict.__init__(self) self.__name__ = None self.__parent__ = None self.website_id = website_id session = Session() website = session.query( PloneContent ).with_polymorphic( PloneWebSite ).filter( PloneContent.id==website_id ).first() self.title = website.title
  • 28.
    Plango, by AndyMcKay from django.db import models from django.contrib.contenttypes.models import ContentType from utils import normalize_name class Content(models.Model): class Meta: db_table = u'content' content_id = models.IntegerField(primary_key=True, editable=False) id = models.CharField(max_length=256, editable=False) uid = models.CharField(unique=True, max_length=36, editable=False) portal_type = models.CharField(max_length=64, editable=False) status = models.CharField(max_length=64, editable=False, null=False) type = models.CharField(max_length=64, editable=False) container = models.ForeignKey('self', related_name=&quot;parent&quot;, editable=False)
  • 29.
    Anyone? Turbogears PylonsWerkzeug Anything goes!
  • 30.
    Content Mirror iseasily extended How about? Reporting against the content Audits of changes Export to formats like JSON Other storage backends Content mirror Uses the Zope Component Architecture We can easily plug in something other than a relational database
  • 31.
    By the way,don't worry about the Component Architecture. We have studied the Zope CA so you don't have to.
  • 32.
    A Google AppEngine frontend Take advantage of Google's infrastructure Use their user authentication facilities Let them worry about scaling Of course, kinds of sites are limited, due to GAE's strict quotas More like a toy, but shows what can be possible using Content Mirror with Plone
  • 33.
    GAE front endapplication import os import wsgiref.handlers from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext import db from google.appengine.ext.db import polymodel from google.appengine.api import users class PloneContent(polymodel.PolyModel): id = db.StringProperty() uid = db.StringProperty() portal_type = db.StringProperty() status = db.StringProperty() type = db.StringProperty()
  • 34.
  • 35.
    All discussed frontends will be made available during the sprints. Keep an eye on: http://contentmirror.googlecode.com/
  • 36.
    Case study TheLibrary of Congress in Chile
  • 37.
    Create multiple sitesin one instance
  • 38.
    Select content froma shared store
  • 39.
    Define a uniquesite layout and style
  • 40.
  • 41.
    Let Plone bea part of the Python universe
  • 42.
    Thank you! Carlosde la Guardia email: [email_address] twitter: cguardia blog: http://blog.delaguardia.com.mx