Andy McKay

Apr 22, 2008

Converting Plone to Django


I've got quite a few Plone sites floating around. And quite a lot of those sites I end up maintaining and I don't really want to, I'd really like it if someone else could. Further those sites aren't really suited to Plone. They are more external brochure ware sites. Mostly static with a small number of editors and no looking at the Plone interface at all. For those sites, Plone is a fine choice, but it's really not its main strength.

So after talking about how much I like Django I thought it was time to start actually doing something. I took one of our Plone sites and said: can I convert this to Django in a weekend? And the answer is simply no. I was hampered by sucking at coding and the family wanting attention. After a few nights of messing around I thought it was time to kick something out and see if I can get on to the next few things in my rather long queue.

First off, converting Plone to Django is a hopeless task, Plone is so big and has so many features that this is a very, very, very big project. All I was initially curious in was my site, could I convert over some content types, pull the data over, set up the URL's and put the views up. This would not mean doing things like security, i18n, users, properties, topics, gosh anything useful at all. So with that caveat, here goes.

Django needs some models, rather than hard code them, how about a little conversion script that goes and reads your Archetypes schema and outputs a Django model. I picked a few fields I really wanted and pulled out some key fields into a metadata (such as effective date), tell it the models you want and you'd get:

class Document(models.Model):
    uid = models.CharField(max_length=255, help_text="Should not  [snip]")
    title = models.CharField(max_length=255, blank=False)
    description = models.TextField(help_text="A short summary [snip]", blank=True)
    text = models.TextField(blank=False)
    ...

Because things like reference fields or lists are unclear, it just skips over those. All possible, but a little too much for the moment.

So you'll get a project and app which I called plango with a bunch of models. Next we want to run through the database and pull out the object and write them into Django, that's a matter importing Django inside a zopectl run script. The magic code to pull the fields out of the content types so I can get them from Zope is:

obj._meta.fields

...that gives you the Django fields. One thing that is important is that the URL's which are great in Plone are maintained. For that there's a urlpaths model that keeps track of the url for that object. It uses Django signals and we rip off and grab the normalize function from Plone to make a nice URL like about/my-company.

Once that's done, we've got our objects in and accessible through the Django admin interface. Wee. The changing is pretty easy, all the fields are there in the Django interface, once you click on edit. Oh sigh if now we could just get Kupu in, which is still the best editor out there.

Next there was a piece of middleware which grabs the url such as about/test and grabs the relevant page in urlpaths. There's a bit of magic that grabs the object and then looks up a default view for that object. The view is a page template, yay, for example in document.pt:

        <h1 tal:content="object/title" class="documentFirstHeading">
          Title or id
        </h1>

Using the templates was easy, I was able to just drop main_template in, and then spend an ages ripping everything out that I wasn't going to build out tonight. And the end result is extremely unremarkable screenshot to our right.

Phew. Well it was an interesting exercise, it's certainly something that needs a great deal of work to continue before its useable, although might be an interesting tool on top of things like entransit. Certainly I feel that if I to start upgrading those Plone sites, I will be working on this tool instead.

Disclaimer: this won't work, if it does I'll fall over with shock. But here's some code:

http://svn.clearwind.ca/public/django/plone-django