'''
This document will only be of interest to a select few, as the process it outlines only applies to (I hope) an uncommon situation. That situation being the need to integrate a Django site, or at least content generated by the Django framework, with a pre-existing Zope or Plone instance. In my case, I had created a corporate intranet using Plone and a handful of Plone 'Products', whose functionality was not conducive to rewriting from scratch; however, I also wanted to write the site-specific business logic aspects of this intranet system in Django, for various reasons I won't go into here.

Because the primary look-and-feel and navigational elements of the site were in Plone, and because the business logic did not require much integration with said elements, it made sense to have Django output basic HTML which could be included as the main content 'text' of the greater Plone site. Therefore, the main challenge was to effectively translate a Zope request object into something that Django could understand, and then return information that could be integrated back into the Plone site.

I expect that others using this information in their own projects may have differing needs, but this example should be easily modified to meet any such demands, as it's primarily just a translation of one dict-like object into another. In fact, it's so simple that my diatribe here threatens to overshadow the actual example, so I'll move on to the details and then let the code speak for itself.

---

My site is set up such that there are a handful of identical Zope Page Template scripts in the root of my Plone instance, each named for a particular section which is handled by the underlying Django site. This is done so that I may allow Django to handle differing root 'directories' on the site; a possibly simpler alternative is to bundle all the custom code into one such section and thus get away with only one script.

These ZPTs create a shell identical to the rest of the site, with regards to navigational elements and so forth; they then query the sole method of an installed Product [[INSERT CODE HERE?]] with the current Zope context object, expecting a dictionary in return. The script then uses values from this dictionairy to fill in the page title, navigation breadcrumbs, and content HTML.
'''

import re
from urllib import quote_plus,urlencode
from StringIO import StringIO

from django.core.servers.basehttp import ServerHandler
from django.core.handlers.wsgi import WSGIHandler

from Products.CMFCore.utils import getToolByName


def switch(self,context):
     """Requires a Zope context object"""
     
     ## Setup
     
     # Zope request object
     request = context.REQUEST
     
     # Grab the first item in the URL hierarchy; this is equivalent to 'foo' in the URL 'http://www.mysite.com/foo/bar/baz
     section = request.URL.split('/')[-1]
     
     # 'traverse_subpath' returns a list of the URL items that are "past" whichever section script was called. So for example, if one Django-controlled section lives under '/contacts/', and a user visits '/contacts/25/edit/', 'traverse_subpath' is populated with the list ['25','edit']
     pathinfo = request.traverse_subpath
     
     # In order to get the full URL back together, we have to put the 
     pathinfo.insert(0,section)
     
     # Django hooks
     pl = []
     for key,value in request.form.iteritems():
         if type(value) is not list:
             pl.append(quote_plus(key)+"="+quote_plus(value))
         else:
             pl.extend([quote_plus(key)+"="+quote_plus(x) for x in value])
     POST = "&".join(pl)
     environ = {
         'PATH_INFO': '/'+'/'.join(pathinfo)+'/',
         'HTTP_HOST': '',
         'QUERY_STRING': request.environ.get('QUERY_STRING',''),
         'REQUEST_METHOD': request.environ.get('REQUEST_METHOD',''),
         'wsgi.input': StringIO(POST),
         'CONTENT_LENGTH': len(POST),
         'ZOPE_USER': getToolByName(context, 'portal_membership').getMemberById(context.REQUEST.AUTHENTICATED_USER.name),
         'SESSION': request.SESSION,
     }
     
     start_response = ServerHandler(None,None,None,environ).start_response
     
     # Get body text from Django
     bodyText = WSGIHandler()(environ,start_response)[0]
     
     # Get title from the page's H1, if exists, otherwise just use section capitalized
     results = re.findall(r'<h1>([^<]*?)</h1>',bodyText,re.I)
     if len(results):
         title = results[0]
     else:
         title = section.capitalize()
     
     # Breadcrumbs generation
     bc = []
     previous = ""
     trail = [""]
     trail.extend(request.traverse_subpath)
     for part in trail:
         if previous=="/":
             previous=""
         url = str(previous)+"/"+str(part)
         bc.append((part,url))
         previous = url
     
     # Return three-part dict for use in the stub ZPT in Zope
     return {
         'body': bodyText,
         'title': title,
         'breadcrumbs': bc,
     }