Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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


Published on

What if you could use Plone only as a CMS and program a frontend in whichever Python web framework you want, with transparent access to the content? This way you get a proven, high-reward, low-maintenance CMS as a content backend and are free to write your application on top of that using the power and flexibility of your favorite web framework.

Published in: Technology
  • Be the first to comment

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. Why?
  3. Plone is the best CMS that is NOT written in PHP
  4. Plone has lots of great features <ul><li>Easy to use and install </li></ul><ul><li>Standards and accessibility compliant </li></ul><ul><li>Best security track record of any major CMS </li></ul><ul><li>Available in more than 40 languages </li></ul><ul><li>Workflow capabilities and rules engine </li></ul><ul><li>Versioning, history and reverting content </li></ul><ul><li>And, of course... </li></ul>
  5. Python
  6. but...
  7. Plone is complex
  8. Plone can be slow
  9. Caching is not always the answer to traffic
  10. Plone is NOT a general web development framework <ul><li>But sometimes we forget that... </li></ul><ul><li>Or clients push us to add features “We want Plone, only take this out and add a couple of features” </li></ul><ul><li>Or we simply don't think we have an option </li></ul><ul><li>So, we end up with... </li></ul>
  11. Frankenplone
  12. It doesn't have to be like this. You can work with your favorite tools.
  13. Content Mirror by Kapil Thangavelu
  14. Content Mirror serializes Plone content into a relational database <ul><li>Out of the Box support for Default Plone Content Types and all built-in Archetypes Fields. </li></ul><ul><li>Supports Any 3rd Party / Custom Archetypes Content. </li></ul><ul><li>Supports Capturing Containment / Content hierarchy in the serialized database. </li></ul><ul><li>Completely Automated Mirroring, zero configuration required beyond installation. </li></ul><ul><li>Support for Plone 2.5, 3.0, and 3.1 </li></ul>
  15. It's simple
  16. Now we can: <ul><li>Use Plone only to manage content </li></ul><ul><li>Use whatever framework we like to work with the content </li></ul><ul><li>Take Plone out of the deployment plans </li></ul><ul><li>Stop worrying about how to do something in terms of Plone and instead think about what we want to accomplish </li></ul><ul><li>Simplify, simplify </li></ul>
  17. And we can serve Plone content fast!
  18. How does it work? <ul><li>Integrates into Plone's event stream and subscribes to content lifecycle events (object added, edited, deleted). </li></ul><ul><li>Transform Plone content schemas into relational tables, using SQLAlchemy. </li></ul><ul><li>All objects get a default content schema, including files and relations. </li></ul><ul><li>Each Plone content type gets its own table. </li></ul>
  20. Installation <ul><li>Download: </li></ul><ul><li>Install </li></ul><ul><li>Configure database </li></ul><ul><li>Configure custom content types </li></ul><ul><li>Generate tables </li></ul><ul><li>Bulk load pre-existing content </li></ul>
  21. Configure the database with ZCML <configure xmlns=&quot;; xmlns:db=&quot;; xmlns:ore=&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 content types For each custom content type installed on the site: <ore:mirror content= &quot;Products.ATContentTypes.content.document.ATDocument&quot; />
  23. Generate tables and upload content dropdb plone createdb plone --encoding=UTF-8 # generate table definitions and create tables bin/instance run parts/productdistros/ContentMirror/ postgres > mirror.sql psql plone < /home/andy/plone/zinstance/mirror.sql # optionally, load existing content bin/instance run parts/productdistros/ContentMirror/ Plone
  24. That's it. We're ready to rock & roll
  25. 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)
  26. What kind of sites can take advantage of this strategy? <ul><li>Sites with a small number of content managers and a large number of users. </li></ul><ul><li>Which can clearly separate content management and presentation. </li></ul><ul><ul><li>Magazines </li></ul></ul><ul><ul><li>Newspapers </li></ul></ul><ul><ul><li>Government </li></ul></ul><ul><ul><li>Non-profits </li></ul></ul>
  27. 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( ).first() self.title = website.title
  28. 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)
  29. Anyone? <ul><li>Turbogears </li></ul><ul><li>Pylons </li></ul><ul><li>Werkzeug </li></ul><ul><li>Anything goes! </li></ul>
  30. Content Mirror is easily extended <ul><li>How about? </li></ul><ul><ul><li>Reporting against the content </li></ul></ul><ul><ul><li>Audits of changes </li></ul></ul><ul><ul><li>Export to formats like JSON </li></ul></ul><ul><ul><li>Other storage backends </li></ul></ul><ul><li>Content mirror Uses the Zope Component Architecture </li></ul><ul><li>We can easily plug in something other than a relational database </li></ul>
  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 App Engine frontend <ul><li>Take advantage of Google's infrastructure </li></ul><ul><li>Use their user authentication facilities </li></ul><ul><li>Let them worry about scaling </li></ul><ul><li>Of course, kinds of sites are limited, due to GAE's strict quotas </li></ul><ul><li>More like a toy, but shows what can be possible using Content Mirror with Plone </li></ul>
  33. 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()
  34. Plone content in GAE
  35. All discussed front ends will be made available during the sprints. Keep an eye on:
  36. Case study The Library of Congress in Chile
  37. Create multiple sites in one instance
  38. Select content from a shared store
  39. Define a unique site layout and style
  40. Deploy sites using repoze.bfg
  41. Let Plone be a part of the Python universe
  42. Thank you! Carlos de la Guardia email: [email_address] twitter: cguardia blog: