Andrew Wilkinson

Random Ramblings on Programming

Updating CouchDB Views In Django

with one comment

CouchDB views are a bit like stored procedures in a traditional database system. As with stored procedures it’s difficult to keep them in sync with your code, and to keep them in your version control system. In this article I’ll show you how you can use a django management command to update your views from files in your code base.

CouchDB uses a map/reduce system where each view is made of a filter program (the map) and an optional post processor that runs over the output of the map (the reduce). These pairs are grouped into design documents which are stored as a single unit in the couchdb database.

This command assumes that you store your map and reduce functions in the directory structure set out below.

                        map.js reduce.js
                        map.js reduce.js
                          map.js reduce.js

Inside your app directory create a folder called couchviews. Inside that create one for each of your CouchDB databases. Finally, create two layers of directories to represent the design documents and views stored within. Each javascript file should contain a single anonymous function.

For this management command to work your settings file needs to contain a variable for each database, containing the Python CouchDB database objects. In this example three variables need to be added to ettings.pydatabase1, database2 and database3.

Add the code below to the file project/app/mangement/commands/ and when you type updatecouchviews it’ll walk your directory structure and update all your design documents in one fell swoop. Easy!

import couchdb
import glob
import os

from import NoArgsCommand

class Command(NoArgsCommand):
    help = "Update couchdb views"

    can_import_settings = True

    def handle_noargs(self, **options):
        import settings

        couchdir = os.path.realpath(os.path.split(__file__)[0] + "../../../couchviews")

        databases = glob.glob(couchdir+"/*")
        for d in databases:
            if not os.path.isdir(d):

            db = getattr(settings, d.split("/")[-1])

            for design in glob.glob(d + "/*"):
                design = design.split("/")[-1]
                    doc = db["_design/" + design]
                except couchdb.client.ResourceNotFound:
                    doc = {"_id": "_design/" + design}

                doc["views"] = {}
                for mapreduce in glob.glob(d+"/"+design+"/*"):
                     mapreduce = mapreduce.split("/")[-1]
                     mr = {}
                     mr["map"] = open(d+"/"+design+"/"+mapreduce+"/map.js").read()
                         mr["reduce"] = reduce = open(d+"/"+design+"/"+mapreduce+"/reduce.js").read()
                     except IOError:

                     doc["views"][mapreduce] = mr

                db["_design/" + design] = doc

Written by Andrew Wilkinson

March 11, 2009 at 1:24 pm

Posted in couchdb, web development

Tagged with ,

One Response

Subscribe to comments with RSS.

  1. […] that I have created are extremely simple and could easily be represented using SQL. Although I wrote some code to help make life easier, creating a view such as that below is never going to be as simple as […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: