Technobabble
Hacking Django forms for CSS flexibility
The default output of the Django forms (former newforms) module is not very CSS friendly. With a few simple adjustments, you can make your web designer colleague happy.
This patch will add three classes on the parent HTML element of the rendering of each form field (the tr, li or p tag depending on your rendering mode):
- The type of the form field. (Examples: CharField, ModelChoiceField)
- The type of the widget. (Examples: TextInput, SelectInput)
- Is the form field optional or required: Optional or Required
- Now a required DateField will render, using the as_table rendering, as:
1 <tr class="DateField TextInput Required">
2 <th>
3 <label for="id_date">Date</label>
4 </th>
5 <td>
6 <input type="text" name="date" id="id_date" />
7 </td>
8 </tr>
Example uses
A couple of example use cases where my patch will help you out:
- Special styling of required fields possible.
- Easier to add a date picker by JavaScript.
- Special styling of checkboxes (styling input elements to width: 100% also affects those).
How to patch your newly downloaded Django-1.0.tar.gz
For those of you not quite familiar with working with patches:
$ wget http://www.hacktheplanet.dk/export/HEAD/misc/forms.py.patch
$ wget http://www.djangoproject.com/download/1.0/tarball/
$ tar xvfz Django-1.0.tar.gz
$ patch -d Django-1.0/django/forms/ < forms.py.patch
Django and mod_wsgi: A perfect match!
mod_wsgi is an Apache module for serving WSGI-based Python web applications from the Apache HTTP server. Django, along with almost every other Python web framework today, comes bundled with a backend for acting like a WSGI application.
A couple of months ago I decided to try it out in spite of mod_python. Discovering and trying out mod_wsgi really suprised me. It can take a massive beating, and outperforms mod_python in every practical aspect.
The setup
You will need a short Python "bootstrap" script to create a WSGI-handler for your Django project. Here is an example (call it wsgi_handler.py and place it in the root directory of your Django project - the one with manage.py and settings.py):
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
os.environ['DJANGO_SETTINGS_MODULE'] = 'projectname.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Finally set up your Apache virtualhost to use mod_wsgi:
<VirtualHost *>
ServerName www.projectname.org
ServerAlias *projectname.org
Alias /admin_media /usr/lib/python2.4/site-packages/django/contrib/admin/media
<Location /admin_media>
Order allow,deny
Allow from all
</Location>
Alias /media /home/user/projectname/media
<Location /media>
Order allow,deny
Allow from all
</Location>
WSGIScriptAlias / /home/user/projectname/wsgi_handler.py
WSGIDaemonProcess projectname user=user group=user processes=1 threads=10
WSGIProcessGroup projectname
</VirtualHost>
In the WSGIDaemonProcess line, you can easily manage the amount of system resources (measured in processes and threads) mod_wsgi should use. In my experience a single process with 10 threads will cover most small to medium loaded websites.
Why?
This is some of the reasons why you should ditch mod_python for mod_wsgi when hosting Django projects:
- Faster
The load times of the websites now served with mod_wsgi really surprised me. Normally a page would be served within 150-300 ms. This was reduced to load times in the range of 40-80 ms.
I also discovered that running mod_wsgi in embedded mode (as opposed to daemon mode) was not worth the effort. I didn't really see any difference between load times when using Django.
- Less memory usage
Everyone hosting more than a couple of Django projects on a single Apache instance knows that Django projects squanders a bit with memory usage, and every single Apache child process will easily end up using 50 MB RAM.
mod_wsgi dedicates a process (or multiple processes) to a single interpreter for a single Django project, and keeps the memory usage low in the "normal" Apache child processes. On a server with 8 small Django projects, I went from using ~1500 MB RAM on Apache child processes to using 150 MB.
- Secure
When using mod_python your Python interpreter will be running as the user running the Apache webserver itself (on Debian systems, the user is called www-data). Typically this will allow you to peek around in places where you do not want your users peeking. This is due to the fact that www-data must have read access to every file you use in your application (including settings/configuration/media files).
mod_wsgi addresses this problem by changing to a user id specified in the configuration file, and run your Python interpreter as another user than www-data, allowing you to lock down every project on your server to seperate user accounts.
These points cover mod_wsgi running in daemon mode.
Conclusion
mod_wsgi rocks!
So if you are thinking about moving your systems to, or just curious about, mod_wsgi, you should really get to it. I, for one, welcome our new mod_wsgi overlords! (sorry)
Futher reading
- How to use django with mod_wsgi (from the Django wiki)
- Integration With Django (from the mod_wsgi wiki):