Leveraging CouchDB in Django

Djangonauts May 3, 2011

Adam "Cezar" Jenkins emperorcezar@gmail.com

How we use CouchDB
‡ Not as a replacement for the Django ORM ‡ Only where it fits ‡ Leverage the Django ORMs strengths ‡ Maybe use it fully when it is better supported

Benefits
‡ Quick retrieval of large data sets. ‡ Document based records
o

Prospective student applications went from 7 models to 1 document. Including resume, essay, and portfolio as attachments Documents in CouchDB are JSON Lists, Dictionaries, and nesting thereof.

o o o

‡ Provides convenient api to access CouchDB ‡ Django Extension

Setup:
COUCHDB_DATABASES = ( ('appid.apply¶, 'http://127.0.0.1:5984/apply¶), ) INSTALLED_APPS = ( .... 'couchdbkit.ext.django¶, .... )

Models:
from couchdbkit.ext.django.schema import * class Greeting(Document): author = StringProperty() content = StringProperty(required=True) date = DateTimeProperty(default=datetime.utcnow)

CouchDB Views:
function(doc) { if(doc.doc_type == 'Application'){ emit(doc.user, doc); } } Couchdbkit allows you to keep your views in your source tree.
apply/_design apply/_design/views apply/_design/views/by_userid apply/_design/views/by_userid/map.js To create databases and sync CouchDB views, just run the usual `syncdb` command.

How we used it
‡ Used user.id to combine records ‡ May not work in other situations
from apply.models import Application
def get_application(user): application = Application.view('apply/by_userid', key=user.id).first() if not application: raise Application.DoesNotExist, "User %s, no application found" % (user,) return application

Easy to integrate
‡ Django forms mostly use dictionaries
import apply.forms as forms application = get_application(request.user) form = forms.ApplicationForm(initial=application._doc) if form.is_valid(): application._doc.update(form.cleaned_data) application.save()

‡ CouchDBKit does have ModelForms, but were not used.

Speed
‡ Sometimes using the couchdbkit models is just too slow
from apply.models import Application results = Application.view('apply/by_userid').all() 4060.605 ms from couchdbkit.ext.django.loading import get_db db = get_db('apply') results = db.view('apply/by_userid').all() 745.735 ms

Attachments
Uploaded Files
form = forms.EssayForm(request.POST, request.FILES) if form.is_valid(): uploaded_file = request.FILES['essay'] application.put_attachment(uploaded_file, name = unicode(uploaded_file.name), content_length = uploaded_file.size) application.save()

Downloading Attachments
def download_file(request, application, attachment_name): attachment = application.fetch_attachment(attachment_name) response = HttpResponse(attachment, content_type= \ application._attachments[attachment_name]['content_type']) response['Content-Disposition'] = 'attachment; filename='+attachment_name return response

CouchDB in Django
‡ Can be very useful for certain types of data ‡ Attachments are an amazing benefit ‡ With CouchDBkit integration is easy ‡ Django forms can be passed dictionaries ‡ Will be great when contrib apps can be loaded onto it.

Sign up to vote on this title
UsefulNot useful