A simple and light-weight wiki solution for Django

I have been running a wiki with structured data for some months now. It’s called CharacterDB and runs on MediaWiki with the SemanticMediaWiki framework. While I was happy to employ one of the best wikis out there (after all Wikipedia runs on MediaWiki) and I have good contacts to some of the guys developing SemanticMediaWiki, I do see some limitations to the task at hand. It makes me want to get rid of the current stack. The major two issues with the solution so far are scalability (> 60.000 entries, the actual count of database entries a far higher due to the RDF triple approach) and the difficulties I have with adjusting the configuration the way I want the input forms to work.

The natural solution for me was to look into a solution with Django. And more importantly using existing components. Looking into wiki apps for Django I found quite a few candidates – there is a fine comparison available under http://djangopackages.com/grids/g/wikis/. However I didn’t like what I saw. What I need is a simple component that would make my models editable by anybody, providing full wiki features. Some of the existing apps implement a full standalone wiki, including authentication, own markup parsers, …

So the idea of django-wiki was born. I already stated coding an initial version, that provides simple wiki features. Have a look if you want under https://github.com/cburgmer/django-wikify .

The feature set includes:

  • Edit view for your model
  • Versioned view of instance
  • Paginated instance versions

There are some other goals I want to reach:

  • lightweight code
  • simple integration
  • easy to adapt (esp. templates)
  • get straight to the point, if it’s not a wiki feature, it shouldn’t be in

django-wikify wouldn’t exist without django-reversion, a neat app that adds versioning to your django models. It has seen many improvements lately and is just the right component to build a wiki on. All I needed to build on top was basically view logic.

Wiki markup can easily be integrated using django’s native markdown integration. No need to develop any additional code. What is missing on my list is support for subscriptions. That, however, I consider an orthogonal feature.

The current code already provides the minimal working set. To setup a wiki yourself you first need to define a model (after all django-wikify is about giving you the flexibility of your own page model). Here is a simple page model, with a title and content:

    from django.db import modelsimport reversionclass Page(models.Model):    """Simple Wiki page model"""    title = models.CharField(max_length=255, primary_key=True)    content = models.TextField(blank=True)    def __unicode__(self):        return self.titlereversion.register(Page)

    The example view is very simple. We just want to show the instance and in case it doesn’t exist yet, we provide a page that allows the user to create it.

    from django.shortcuts import render_to_responsefrom django.template import RequestContextfrom wikify import wikifyfrom mywiki.models import Page@wikify(Page)def page(request, object_id):    try:        page = Page.objects.get(pk=object_id)    except Page.DoesNotExist:        page = None    return render_to_response('page.html',                              {'object_id': object_id,                               'page': page},                              context_instance=RequestContext(request))

    What you see here is a simple way to use wikify. Just decorate the view and pass the model with it. The only thing you need to take care of is to pass the object’s primary key as ‘object_id’, similar to Django’s default views. The project code includes an example django project as a short demo using the code shown here.

    The way the @wikify decorator works, you do not need to change your urls.py definition. The action triggered by the user is passed through a GET variable called ‘action’. In case you want to provide your own template, just link to the url ‘?action=edit’ and you are done.

    Next features on my list are support for a diff view based on my side-by-side diff implementation, and then improving performance through ETag, cache, … After that, better late then never, unit tests.