Reinventing the (Wiki) wheel

I have been mulling for some time the idea of creating yet another Wiki engine/application. But before I started building it, I wanted to iron out the reasons why I want to do it. Some reasons seem childish when looked at objectively and others seem frivolous. But when I probe deeper into them, I find myself motivated to at least give it an honest chance.

So far I have asked myself some questions on why not to go ahead with this project. Is there really a need for another Wiki application when a plethora of choices are already available? Isn’t it better to work on a project which doesn’t have as many choices and people working on it? What is it that I can provide in your Wiki application that others haven’t already provided or considered but rejected? Who do I want to target as my audience; individuals, developers, small teams, large teams, etc.? Do I have the time, drive, and commitment to not only start this project but continue to maintain if it is ever finished? In short, I have tried to ask myself questions that would discourage me from going ahead because there’s a side of me that really believes that yet another Wiki engine will not benefit a lot of people. I could rather work on making, for example, a Session Border Controller solution using OpenSIPS and FreeSWITCH, you know, something that a lot more people could find useful.

But there’s another side that really wants to undertake this project for a few reasons. I tried MoinMoin (in fact, still using it) and the biggest problem for me (and I could be wrong here) was that to make changes to config, I have to change Python code. I am certainly capable of understanding Python code and trying to modify it to suit my purpose but the biggest obstacle is to first learn how and where to make the changes. This requires excellent documentation, something not easily done when users may be required to do some short programming stuff. I started with MoinMoin precisely because I feel very comfortable with Python and knew that I could adapt it if required. I love that MoinMoin stores content in flat files, which I can backup using rsync from my server to my notebook. But I don’t get that ‘Oh, I get it!’ feeling when trying to change the way MoinMoin works by default. I could try some other Wiki that does these things but not many are built using Python.

These, and many other, reasons prompted this prospect of re-inventing a Wiki application. Some of the goals, inspirations, and design choices are below.

  • I want to learn how to create a Wiki.
  • Always use the test tool for the job.
  • Leverage already-existing tools rather than re-creating them for no reason.
  • Focus primarily on making a Wiki.
  • First have a functioning Wiki and then think about performance, scalability, serving as true collaboration platform, plug-in support, etc.
  • The same Wiki should serve multiple groups and users with smart and secure permissions.
  • Security features, such as IP whitelist, IP blacklist, account lock on multiple login failures, etc. should be easy to manage.
  • Allow multiple Wikis to be hosted from the same server using either the same database (shared credentials among the farm) or different databases.
  • Wikis are mostly read-only with a small portion of it being edited at any given time. So use flat files for content and attachments. File systems were designed to handle files well so let them do their job.
  • Databases are great for structured data so use them configuration, settings, rules, etc. This deals with the issues of changing code to maintain policy.
  • Differentiate between Wiki Management System (WMS) and content. WMS are all the bits and pieces that make a Wiki function: user management, parsers, etc. Content is what the users most focus on because the Wiki exists to gather and serve content.
  • Advanced, fine-grained user profile and access control management, auditing, and logging.
  • Use Django because that’s what I know best. An additional advantage of using Django is that the project can then be modified by people who know it or it can be integrated/enhanced into a much bigger Django project.
  • Python and Django make it easy to create a multi-platform application but focus primarily on Linux.
  • Keep the project free, open source, and freely available.

Some wishlist items are also included.

  • Add some elements of blogs, such as tags, time-sensitivity of content, discussions, etc.
  • RSS feeds.
  • Simultaneous editing for a true multi-user Wiki.
  • Integration with different authentication/authorization methods, such as RADIUS, LDAP, etc.
  • Use YUI Library to create user-friendly and pretty templates, etc.

Now the question I ask myself is this: how much time and effort will be required to get this project started and rolling. This is a huge list of goals for a single developer (who is a developer-for-fun in the first place). Am I capable of managing this project? Only time will tell. But the last question I ask myself before I start: is it worth it to reinvent the wheel when others have already done pioneering work before you?

Django, Apache, and X-SendFile in Debian

The idea for this post is to allow downloading files only to restricted users. The only constraint for now is that users are logged in. As I add more code to the Django app, I plan to include the ability to specify which users should have access to which files.

This post assumes that you have a working Apache server with VirtualHost file setup for a Django project. I also assume that you would want to access files using a URL scheme such as where filename.ext represents the file you want to download.

To install X-SendFile in Apache2, run the following:

sudo aptitude install libapache2-mod-xsendfile

And to make sure you enable it, run the following

sudo a2enmod xsendfile

Add the following two lines in your VirtualHost file, like so:

<VirtualHost *:80>
XSendFile on
XSendFileAllowAbove on

The code for this has been uploaded to Launchpad under the project Django X-SendFile Download or DjangoXSFD for short. Since it’s a work in progress, you can always get the latest code from there.

Hat tips: Djangocon X-Sendfile Lightning Talk; Fast File Transfer with X-send file; How to make a private download area with django?; Having Django serve downloadable files; Fast private file transfers for Drupal;

Django – Logging in Views

I have searched as many places I could looking for an advisable way of logging within views in Django. I found a lot of advice, apps, code, etc. But I did not find anything easy, beautiful, or even understandable for someone with my limited knowledge. So I did what anyone in need would do: create an app of my own which can be used within for any and all apps and projects.

The main idea was to use Python’s logging module but abstract it enough so that any developer can configure it easily. The code has been structured thus: a directory called django-logbook (or even djangologbook) which needs to be placed on Python’s path, preferably in the Django project folder. This directory contains at least three files, with more files included depending on the number of apps using Django-LogBook (my name for the app). These three files are:,, and is empty and is present so that the logbook directory can be considered a package or module by Python. contains the heart of the app. It contains a class calls LogBook which can be instantiated by any app. To make things easier in terms of management, I have added a which does the instantiation. The idea is to create separate log files for separate apps. Therefore, each app has its own in the logbook directory. Just copy and rename it as Then in your import the

You don’t even have to import the whole in All you have to do is import as below:

from PROJECTNAME.logbook.APPNAME import djangologbookentry

Then within your views, you can log as below:'My info message')
django-logbookentry.error('2009-12-16 23:59', 'OMG an error')

In your in django-logbook directory, you need to provide three things: unique identification of logger for the app, name of the log file, and level of log messages. By default it is setup to log up to 5 files, each file 200,000 bytes in size.

For detailed configuration, you can view and modify the LogBook class.

The code for Django-LogBook is hosted at Launchpad.

When to use GET and POST

In HTTP and/or HTML, there are two (main?) types of submissions: GET and POST. I have always had a hard time determining when to use GET and when to use POST. In other words, what is the main difference between GET and POST?

Quite simply, if the submission is reading data, without making any changes, use GET. If your submission will be making changes, or causing side-effects, use POST. For example, when doing a query, such as a Google search, the form should use GET. If you are creating a new account with Yahoo! mail, the form should use POST. The Google search is reading data and new account in Yahoo! mail is changing things.

Simple enough, right? Not so, as there are some situations where either could work. One of the best descriptions of the problem I have read is Methods GET and POST in HTML forms – what’s the difference? And here is what I learned from it (you might learn something else reading the same words):

When doing a submission which will not make changes use GET. When making changes, use POST. But you may want to use POST instead of GET in the following (major?) case: when you don’t want the data you submit to become a part of the URL. When using GET, the form you submit becomes a part of the URL. So if you have a couple fields, say myname and mynumber, using GET your URL might look like after submission. The biggest benefit is that you can bookmark this URL and visit it in future as just another link. The biggest disadvantage, in my opinion, is when you have multiple fields, the fields and their data becomes part of the URL, thus making for ugly URLs. So instead of a neat looking, small URL, you get one huge string.

Don’t get me wrong: a useful URL, even if ugly, should be preferred to an unfriendly, pretty URL. But if you want to pretty-fy your URLs, use POST instead of GET. And with a pretty URL, your user doesn’t have to know the inner workings of your form. They can still look at the source code of the page to see what’s going on, but only if they want to. Encoding the form data into a URL forces them to deal with the data even if they don’t want to.

The second benefit of using POST is that if your form contains non-ASCII data, it doesn’t form a part of the URL, which might be a good thing if your HTTP server is unable to handle this data in the URL. I don’t know, maybe all modern servers or intermediary devices can handle this stuff easily. But better safe than sorry, eh?

So from today my best practice is thus: if the form has a small number of fields, showing the submitted data in the URL is not a problem, and/or URL should be bookmark-able for future reference, use GET if there are no side-effects. If none of these requirements is met, use POST.

One concern I have is: if using HTTPS, is the URL sent in the secure tunnel or is it plaintext for all to see? According to the responses at HTTPS – is URL string itself secure??, the URL should be encrypted before being sent to the server as it is sent as part of the tunnel rather than a separate string. I think it would depend on the implementation of the client and server (I could be wrong in thinking this).

Don’t take my understanding of the situation as the final word. Read as much as you can on the subject to form your own best practice. And if you share your understanding and best practice with us, it would help us as well.

Good reads and hat tips: URIs, Addressability, and the use of HTTP GET and POST; Methods GET and POST in HTML forms – what’s the difference?; Post/Redirect/Get;

Django in Debian Lenny

Installing Django in Debian is very similar to in Ubuntu. Here we will use Postgresql so there will be a slight difference from when using MySQL.

sudo aptitude install postgresql python-psycopg2 python-django

Django in CentOS

This post has been written using CentOS 5.2, but these instructions may also work for other versions. Just let us know if they don’t.

Install EPEL

Extra Packages for Enterprise Linux (EPEL) is “a repository of high-quality add-on packages that complement the Fedora-based Red Hat Enterprise Linux […] and its compatible spinoffs such as CentOS or Scientific Linux.” You need this repository to install Django from a package. Another option is to download source and compile yourself. This guide, however, will be using packages. So just follow the instructions to add EPEL repository, which state:

su -c 'rpm -Uvh'

Install Django

To install django from EPEL, just run the following command:

sudo yum install Django

Notice the uppercase ‘D’ in the name of the package. Django is installed in /usr/lib/python2.4/site-packages/django/ and it should already be included in the path.

Test Django

To make sure everything was installed properly, try to create a simple new project. startproject /home/me/mynewproject

If a directory with the same name and some standard django sub-directories are created, then your installation was successful.