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.
o Including resume, essay, and portfolio as attachments
o Documents in CouchDB are JSON
o Lists, Dictionaries, and nesting thereof.
• 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.