Django Login Session ID Extractor Script

In the not too distant past, I worked on an interesting web project in which my participation lasted a brief period. I enjoyed the time I spent working on it. It was a project based on Django and Python, two technologies that I simply love working with. The last tasks I worked on had to do with benchmarking the performance of the Django web application, as well as the webserver it was powered on, which was Apache.

I had to use the excellent and extensive Apache Benchmark utility, also commonly known as simply ab. If you’re not familiar with ab, I recommend you check it out. The problem I faced was not being able to benchmark views that required an authenticated web session. Simply put, I wasn’t able to use ab against views that were login protected. In order to solve this limitation and also to automate the process, I threw together a BASH shell script which I called The Django Login Session ID Extractor. It used a combination of Linux tools to log into the Django application via the login view, and extract out the SESSION ID thus created. This SESSION ID, then, could be passed to the ab command in order for it to hit login protected views.

This script proved really useful during testing, and would’ve even more had I continued to work on it. However, I decided to make the script available on GitHub for the world to use. I am hoping someone might make use of it.

Advertisements

A guide to configuring two different Django versions for development

Django 0.9x and Django 1.x branches are so far apart that a project built on top of the former, not least when it has been rolled off into production, that porting it to the 1.x branch of Django can easily escalate into a nightmare. If you have to maintain a legacy Django project — I choose to call projects built on anything before 1.x legacy –, you will find that it is easier if you maintain two different versions of Django on your development environment. How do you do that, is the quagmire this post revolves around.

I prefer Apache with mod_python to Django’s simplistic development web-server for Django projects. Initially, the task of setting up mod_python and Apache to your tastes may seem daunting. However, once you get around its not so steep curve, the difficult task becomes second nature.

I am working with Python 2.5 on a project with Django 1.0.2. Django is deployed on the system in the site-wide default directory for third-party Python modules and applications. I also have to support development for a legacy application built on Django 0.97 (a trunk snapshot from a time long ago). My requirement is simple: I want to be able to run both projects simultaneously without having to muck around tweaking configurations besides the one time when I set the projects up.

A garden-variety solution is to change the default Django directory in the Python path to point to the specific Django that is the need of the moment. This approach puts upfront a limitation of not being able to run both projects side by side. It also is annoying because it requires tap-dancing around Django directories when switching between the two versions. It is not a considerable blow to productivity, but if it can be avoided for a better, more efficient solution, there is no reason not to.

The solution I am proposing involves having the recent Django set up as the default, with the legacy Django installed in a different directory—after all, the legacy Django is the odd item of the group. I develop on an OS X environment, where I have the two Django versions set up thus:

/Library/Python/2.5/site-packages/django
/Library/Python/2.5/site-packages/django-0.97/django

You can probably tell which is which.

I have both projects deployed as virtual hosts on Apache, each running off of the root of the web-server without stepping on the feet of the other. They can easily instead be set up to, instead of the root of the web-server, serve from under a unique sub-URL path. That is mostly a matter of preference.

For each virtual host, I have assigned a domain name based off of the name of the project. I should emphatically point out that these domains are set up to resolve to localhost on my system. They may likely have real world twins that are routable over the Internet, but for all intents and purposes, they are local to my development environment. I have done it so, partly out of convenience, and partly because one of the projects hinges on subdomain-based user-to-account mapping (what this means, simply, is that registered users on the project are assigned different accounts that directly relate to subdomains, and can log in to the project only via their respective subdomains) for proper functioning. For the latter, the domain based approach was inevitable.

With that in mind, here are the virtual host settings for the two projects

<VirtualHost *:80>
   ServerAdmin root@localhost
   ServerName projectone.com
   <Location "/">
      SetHandler python-program
      PythonHandler django.core.handlers.modpython
      SetEnv DJANGO_SETTINGS_MODULE projectone.settings
      PythonPath "['/Users/ayaz/Work/', 
            '/Users/ayaz/Work/projectone/'] + sys.path"
      PythonDebug On
   </Location>
</VirtualHost>

<VirtualHost *:80>
   ServerAdmin root@localhost
   ServerName legacyproject.com
   <Location "/">
      SetHandler python-program
      PythonHandler django.core.handlers.modpython
      SetEnv DJANGO_SETTINGS_MODULE legacyproject.settings
      PythonPath "['/Library/Python/2.5/site-packages/django-0.97', 
            '/Users/ayaz/Work/', '/Users/ayaz/Work/legacyproject/'] + sys.path"
      PythonDebug On
        </Location>
</VirtualHost>

While each line of the above is important, the following is the highlight of this post:

   PythonPath "['/Library/Python/2.5/site-packages/django-0.97', 
            '/Users/ayaz/Work/', '/Users/ayaz/Work/legacyproject/'] + sys.path"

I have effectively injected the path to Django 0.97 into Python path. What this helps achieve is that when mod_python loads the Python interpreter to serve an incoming request for the project, Python analyses its path, looking for a module named django. The first successful match is under the /django-0.97 directory, which, if I have not already lulled you into sleep, is where Django 0.97 lives.

For the curious, all possible mod_python directives are documented here.

All this is a one-time headache: you pop in a pill, and forget about it. I can now type in projectone.com or legacyproject.com in the browser to get to either project.

I should mention, still and all, that I have of late come to know of virtualenv, a Virtual Python Environment builder. It may be a more proper solution than what I have proposed, but I have not yet used it myself to say more.

I hope I was able to clearly explain what I had intended to.

URL rewriting and WordPress

You may have noticed that WordPress by default creates and uses “Search Engine Optimized or Friendly” URLs. The raw URLs, which refer to the file on disk followed up by a train of grotesque-looking keywords and equals-signs and ampersands and question marks, are hidden from view. For WordPress, the magic comes from what is popularly known as URL rewriting. By sketching out simple or complex yet powerful rules to define what and how to rewrite, you can force the web server to completely transform URLs into clean, beautiful, search engine friendly forms.

Apache, a web server that can commonly be found to be the choice for deployment of WordPress, delegates the entire responsibility of URL rewriting to a module named mod_rewrite. URL rewriting rules can be defined globally, or on a per directory basis, which are interpreted and acted upon by mod_rewrite. In order for rules to be interpreted on a per directory basis, for which these are defined in a special configuration file that can exist within any directory, the AllowOverride setting must be enabled within Apache globally. If it isn’t, rules defined per directory will quietly be ignored.

In order for WordPress to weave its magic, both mod_rewrite and the AllowOverride setting must be enabled within Apache. This realisation dawned upon me when Asim mentioned that the two need to be enabled on Apache. On a server on which I had recently deployed WordPress for a friend, I noticed that created pages beyond the home page would give a mysterious 404. The two, as Asim gratuitously told me, were not enabled on Apache on that server which in turn were causing the 404 to pop out. I am surprised I did not stumble upon these two gotchas documented within WordPress—I may have overlooked, I am not sure.

I hope this serves to help a lost soul fumbling along a similar path.