Project Release: django-axes 0.1-pre

Ever curious to see information about failed login attempts on your site? This morning I threw together a small, simple Django application that allows you to do just that. I'm calling this project django-axes, which is pronounced as "jango access".

I've only tested it on my own site, so it must still undergo some more in-depth testing before I can call it a stable application. From my testing, however, it works exactly as I expect it to.

For more information, check out the project homepage on Google Code.

django-pendulum news

I've made several fun improvements to my Pendulum Django application. Perhaps the most noteworthy for most people is the addition of a default jQuery-powered date picker for adding and updating entries. I was hesitant to make anything like this be required because some people might prefer controls other than the one I chose. However, I tried to make it easy to override this default date picker if you so desire. Hopefully someone will report on how easy/difficult it is.

Also, I've added django-pendulum to the PyPI, which is Python's little package repository. You can think of it as an apt-get repository for those of you familiar with Debian/Ubuntu Linux or derivatives. There is a utility called easy_install, which obviously makes it easy to install packages that are found in the PyPI. The command to install django-pendulum with easy_install is easy_install django-pendulum. Good stuff!

There have been various other changes to the code, and I have some more changes planned. We'll see how long it takes me to get around to making these changes...

Project Release: django-pendulum 0.1

For those of us who like to know how much time we spend on various projects, I've released a little project to help you out. Pendulum is a small Django application that I've been using to keep track of the time I work on my various personal projects. It's very easy to use, and it's been working great for me for several months.

This weekend I took the time to make several improvements that I deemed necessary before I could make the project publicly accessible. While I've done some testing on my own, I'm fairly certain that I haven't tried all combinations of situations, so there might be some problems that you find as you use it.

To learn more, head on over to http://code.google.com/p/django-pendulum/. There you can learn how to download and install it and what you need to do to configure it.

Enjoy!

Python 2.6 Is Available

I haven't been following the development of Python very closely, so I will rely on someone else's information in this post.

The major theme of Python 2.6 is preparing the migration path to Python 3.0, a major redesign of the language. Whenever possible, Python 2.6 incorporates new features and syntax from 3.0 while remaining compatible with existing code by not removing older features or syntax. When it's not possible to do that, Python 2.6 tries to do what it can, adding compatibility functions in a future_builtins module and a -3 switch to warn about usages that will become unsupported in 3.0.

Some significant new packages have been added to the standard library, such as the multiprocessing and json modules, but there aren't many new features that aren't related to Python 3.0 in some way.

Python 2.6 also sees a number of improvements and bugfixes throughout the source. A search through the change logs finds there were 259 patches applied and 612 bugs fixed between Python 2.5 and 2.6. Both figures are likely to be underestimates.

So there you have it! Rock on Python!

Project Release: Seasonal Stylesheets

The other day at work I was involved in a humorous discussion about having our organization's Web site change colors depending on what day of the year it was. We threw around all sorts of fun ideas, knowing full well that it would never happen for our organization. It would be too unprofessional.

That night my allergies were bothering me to the point where I couldn't sleep, so I decided to see what I could do about making our discussion more possible, at least for others who can take a little more creative license than us. By morning, I had a working application that could effectively change the colors on a Web page depending on the date.

Today I released the source code on Google Code, hoping that someone more creative than me might take it and experiment to make something both attractive and useful.

You can learn more at the project's homepage: http://code.google.com/p/django-seasonal-stylesheets/

Installing Django on Shared Hosting (Site5)

This article is a related to my previously posted article about installing Django, an advanced Web framework for perfectionists, on your own computer. Now we will learn how to install Django on a shared hosting account, using Site5 and fastcgi as an example. Depending on your host, you may or may not have to request additional privileges from the support team in order to execute some of these commands.

Note: Django requires at least Python 2.3. Newer versions of Python are preferred.

Note: This HOWTO assumes familiarity with the UNIX/Linux command line.

Note: If the wget command doesn't work for you (as in you don't have permission to run it), you might try curl [url] -O instead. That's a -O as in upper-case o.

Install Python

Site5 (and many other shared hosting providers that offer SSH access) already has Python installed, but you will want to have your own copy so you can install various tools without affecting other users. So go ahead and download virtual python:

mkdir ~/downloads
cd ~/downloads
wget http://peak.telecommunity.com/dist/virtual-python.py

Virtual Python will make a local copy of the installed Python in your home directory. Now you want to make sure you execute this next command with the newest version of Python available on your host. For example, Site5 offers both Python 2.3.4 and Python 2.4.3. We want to use Python 2.4.3. To verify the version of your Python, execute the following command:

python -V

If that displays Python 2.3.x or anything earlier, try using python2.4 -V or python2.5 -V instead. Whichever command renders the most recent version of Python is the one you should use in place of python in the next command. Since python -V currently displays Python 2.4.3 on my Site5 sandbox, I will execute the following command:

python ~/downloads/virtual-python.py

Again, this is just making a local copy of the Python installation that you used to run the virtual-python.py script. Your local installation is likely in ~/lib/python2.4/ (version could vary).

Make Your Local Python Be Default

To reduce confusion and hassle, let's give our new local installation of Python precedence over the system-wide Python. To do that, open up your ~/.bashrc and make sure it contains a line similar to this:

export PATH=$HOME/bin:$PATH

If you're unfamiliar with UNIX-based text editors such as vi, here is what you would type to use vi to make the appropriate changes:

  • vi ~/.bashrc to edit the file
  • go to the end of the file by using the down arrow key or the j key
  • hit o (the letter) to tell vi you want to start typing stuff on the next line
  • type export PATH=$HOME/bin:$PATH
  • hit the escape key
  • type :x to save the changes and quit. Don't forget the : at the beginning. Alternatively, you can type :wq, which works exactly the same as :x.

Once you've made the appropriate changes to ~/.bashrc, you need to make those changes take effect in your current SSH session:

source ~/.bashrc

Now we should verify that our changes actually took place. Type the following command:

which python

If they output of that command is not something like ~/bin/python or /home/[your username]/bin/python, something probably didn't work. If that's the case, you can try again, or simply remember to use ~/bin/python instead of python throughout the rest of this HOWTO.

Install Python's setuptools

Now we should install Python's setuptools to make our lives easier down the road.

cd ~/downloads
wget http://peak.telecommunity.com/dist/ez_setup.py
python ez_setup.py

This gives us access to a script called easy_install, which makes it easy to install many useful Python tools. We will use this a bit later.

Download Django

Let's now download the most recent development version of Django. SSH into your account and execute the following commands (all commands shall be executed on your host).

svn co http://code.djangoproject.com/svn/django/trunk ~/downloads/django-trunk

Now we should make a symlink (or shortcut) to Django and put it somewhere on the Python Path. A sure-fire place is your ~/lib/python2.4/site-packages/ directory (again, that location could vary from host to host):

ln -s ~/downloads/django-trunk/django ~/lib/python2.4/site-packages
ln -s ~/downloads/django-trunk/django/bin/django-admin.py ~/bin

Now verify that Django is installed and working by executing the following command:

python -c "import django; print django.get_version()"

That command should return something like 1.0-final-SVN-8964. If you got something like that, you're good to move onto the next section. If, however, you get something more along the lines of...

Traceback (most recent call last):
    File "<string>", line 1, in ?
ImportError: No module named django

...then your Django installation didn't work. If this is the case, make sure that you have a ~/downloads/django-trunk/django directory, and also verify that ~/lib/python2.4/site-packages actually exists.

Installing Dependencies

In order for your Django projects to become useful, we need to install some other packages: PIL (Python Imaging Library, required if you want to use Django's ImageField), MySQL-python (a MySQL database driver for Python), and flup (a utility for fastcgi-powered sites).

easy_install -f http://www.pythonware.com/products/pil/ Imaging
easy_install mysql-python
easy_install flup

Sometimes, using easy_install to install PIL doesn't go over too well because of your (lack of) permissions. To circumvent this situation, you can always download the actual PIL source code and install it manually.

cd ~/downloads
wget http://effbot.org/downloads/Imaging-1.1.6.tar.gz
tar zxf Imaging-1.1.6.tar.gz
cd Imaging-1.1.6
ln -s ~/downloads/Imaging-1.1.6/PIL ~/lib/python2.4/site-packages

And to verify, you can try this command:

python -c "import PIL"

If that doesn't return anything, you're good to go. If it says something about "ImportError: No module named PIL", it didn't work. In that case, you have to come up with some other way of installing PIL.

Setting Up A Django Project

Let's attempt to setup a sample Django project.

mkdir -p ~/projects/django
cd ~/projects/django
django-admin.py startproject mysite
cd mysite
mkdir media templates

If that works, then you should be good to do the rest of your Django development on your server. If not, make sure that ~/downloads/django-trunk/django/bin/django-admin.py exists and that it has a functioning symlink (shortcut) in ~/bin. If not, you'll have to make adjustments according to your setup. Your directory structure should look something like:

  • projects
    • django
      • mysite
        • media
        • templates
        • __init__.py
        • manage.py
        • settings.py
        • urls.py

Making A Django Project Live

Now we need to make your Django project accessible from the Web. On Site5, I generally use either a subdomain or a brand new domain when setting up a Django project. If you plan on having other projects accessible on the same hosting account, I recommend you do the same. Let's assume you setup a subdomain such as mysite.mydomain.com. On Site5, you would go to ~/public_html/mysite for the next few commands. This could differ from host to host, so I won't go into much more detail than that.

Once you're in the proper place, you need to setup a few things: two symlinks, a django.fcgi, and a custom .htaccess file. Let's begin with the symlinks.

ln -s ~/projects/django/mysite/media ~/public_html/mysite/static
ln -s ~/lib/python2.4/site-packages/django/contrib/admin/media ~/public_html/mysite/media

This just makes it so you can have your media files (CSS, images, javascripts, etc) in a different location than in your public_html.

Now for the django.fcgi. This file is what tells the webserver to execute your Django project.

#!/home/[your username]/bin/python
import sys, os

# Add a custom Python path.
sys.path.insert(0, "/home/[your username]/projects/django")

# Switch to the directory of your project. (Optional.)
os.chdir("/home/[your username]/projects/django/mysite")

# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "mysite.settings"

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")

And finally, the .htaccess file:

1
2
3
4
5
6
RewriteEngine On
RewriteBase /
RewriteRule ^(media/.*)$ - [L]
RewriteRule ^(static/.*)$ - [L]
RewriteCond %{REQUEST_URI} !(django.fcgi)
RewriteRule ^(.*)$ django.fcgi/$1 [L]

The .htaccess file makes it so that requests to http://mysite.mydomain.com/ are properly directed to your Django project. So, now you should have a directory structure that something that looks like this:

  • public_html
    • mysite
      • media
      • static
      • .htaccess
      • django.fcgi

If that looks good, go ahead and make the django.fcgi executable and non-writable by others:

chmod 755 ~/public_html/mysite/django.fcgi

After that, head over to http://mysite.mydomain.com/ (obviously, replace the mydomain accordingly). If you see a page that says you've successfully setup your Django site, you're good to go!

Afterthoughts

I've noticed that I need to "restart" my Django sites on Site5 any time I change the .py files. There are a couple methods of doing this. One includes killing off all of your python processes (killall ~/bin/python) and the other simply updates the timestamp on your django.fcgi (touch ~/public_html/mysite/django.fcgi). I find the former to be more destructive and unreliable than the latter. So, my advice is to use the touch method unless it doesn't work, in which case you can try the killall method.

Good luck!

Django 1.0 Final!!

That's right folks! The amazing Django team has announced the immediate availability of Django 1.0 final!

This release is perhaps one of the most highly anticipated events in the Python community. More than three years in the making, the Django Web framework is something that perfectionist developers love and enjoy using. I've been using it for just over a year now, and I can't even remember doing things any other way! It's absolutely amazing!!!

So go ahead and download and install it today! What are you waiting for?!

My First Firefox Extension

Last November, a former co-worker and I began brainstorming for a particular site. This site was intended to give people a way to remember quotes that they heard/read/smelled/absorbed/etc without much effort. Soon thereafter, QuoteBoards.org was born.

The site has been pretty boring until recently, though it has been performing its purpose since its first launch. Up until a couple weeks ago, we only had one truly "faithful" member. This member, dirid51, added quotes to his QuoteBoard regularly. He held the site record of 52 quotes until one day another member (Puck) blew is 52 quotes out of the water with nearly 150 (genuine, I might add) quotes in one day.

I got in touch with Puck, and he shared some invaluable feedback with me concerning QuoteBoards.org. With this feedback, I was able to make several improvements that helped Puck along the way as he added his collection of quotes. Currently, he as 1,002 quotes. Most of these were added within a two or three day window. The reason he's stopped adding quotes is because he's tired of transcribing them from printed documents.

With that in mind, I decided it was finally time to begin working on the Firefox extension that I had originally planned to build for QuoteBoards.org when my co-worker and I were initially brainstorming. The purpose of this extension was to make adding quotes from the Web even easier. So, with a few minutes here and there between laundry and such, I was able to build my very first Firefox extension: Quote Grabber.

Right now, the extension is marked as "experimental" and requires people to log into the Mozilla Add-ons site in order to install and use it. However, if you're feeling adventurous, you can bypass that requirement by installing it directly from QuoteBoards.org. There are also directions for using it there.

I hope that those of you who are reading this find the extension to be beneficial and useful. I had a good time developing it nonetheless.

Django's New Comment System

There are a lot of exciting changes happening with Django right now. A lot. Some of these changes cause a lot of things to break across my sites. One such change was the integration of Thejaswi Puthraya's Summer of Code project: an improved comment system.

The first, and most obvious problem, was the change in the URLconf. This took me a while to track down for one reason or another. Here's the situation: originally, the django.contrib.comments application used a URLconf such as:

(r'^comments/', include('django.contrib.comments.urls.comments')),

This makes any comments-powered pages blow up. To solve this particular problem, just make it:

(r'^comments/', include('django.contrib.comments.urls')),

The next thing that caught me dealt with the templates for comments. Now there are actually some default ones, which is nice, but they might interfere with your own templates. I found that all I need in my templates/comments/ directory now is a single simple template called base.html:

{% extends 'base.html' %}

All of the other templates aren't needed unless you do some customized stuff (which I don't bother with).

Finally, and probably the most frustrating of all, getting an error such as:

NoReverseMatch: Reverse for '<function post_comment at 0xb504a1b4>' not found.

I'm not really sure why this problem has arisen, but my solution for it is to remove the entire django/contrib/comments/ directory and bring it back down from SVN. My guess is that some .pyc file lingering from the original comments application is interfering with the new comments application.

Feel free to post here if you have any other advice or problems!

Project Release: django-tracking 0.1

I'm proud to announce the official release of yet another one of my side projects. I call it django-tracking, and it is a simple project capable of telling you how many users are currently on your site. If you look at the bottom of any page on codekoala.com, you will see a demonstration of what this project can be used for.

django-tracking also offers basic blacklisting capabilities. I had a chap who apparently setup a script to spam my blog with rubbish comments every 11 minutes recently. I devised a way to stop the comments from being posted, but I noticed from my logs that the script was still hitting my website consistently over the following days. As a result, I implemented the "Banned IP" feature in django-tracking, and any visitor (or script) accessing my site from that IP address receives an error page. Yay!

If you have "Big Brother"-like tendencies when it comes to your visitors, there is also a way for you to have a "live feed" of active users on your site. Works pretty well, if I do say so myself :)

For more information, hop on over to django-tracking's homepage. There you will also find installation instructions and details for configuration and usage.

Have fun!