Static Files in Django on Production and Development

For developing a django application, I’ve been using the webserver that comes with django. It’s great for development since there is no need to restart apache. The quick and easy way to server a static file with the django webserver is to use this in your urls.py:

urlpatterns = patterns('',
    (
        r'^files/(?P<path>.*)$',
        'django.views.static.serve',
        {'document_root': '/home/django-proj/files'}
    ),
# ... more url patterns
)

Which worked great for testing things out, but it is definitely not a good idea to use this in a production environment. On the production server I set apache to not bother with mod_python for those directories so that django doesn’t have to do any processing.

Since I wanted to use the same files on each server, I didn’t want the static serve in the url patterns on production. To add more patterns to urlpatterns, you can do urlpatters += patterns(”, to add more. I also added the file locations into settings.py since they would be different for other developers. Using if hasattr(settings, ‘STATIC_FILE_LOCATION’): I was able to keep the urlpatterns in the right format whether it’s in a production or development environment.

An example of what I’m using:

from django.conf.urls.defaults import *
from django.conf import settings
 
# basic urls
urlpatterns = patterns('',
    (r'^logout/', 'myproject.user.views.logout'),
    (r'^login/', 'myproject.user.views.login'),
)
 
# if on a development machine
if hasattr(settings, 'STATIC_FILE_LOCATION'):
    urlpatterns += patterns('',
        (r'^files/(?P<path>.*)$',
        'django.views.static.serve',
        {'document_root':
        settings.STATIC_FILE_LOCATION}),
    )
 
# application urls
urlpatterns += patterns('',
    # add new applications below here
    (r'^user/', include('myproject.user.urls')),
    # end applications
 
    # the index
    (r'^$', 'myproject.user.views.index'),
)

Quick Thumbnails in Django

I normally like to write code myself instead of installing some large script just to do one task for me. There were a few scripts out there that could create thumbnails, but I wanted something simple and wouldn’t use most of those features. Plus, I wanted to know how to use the Python Image Library with Django 1.0 and learn on my own how to take an uploaded picture and create a few thumbnails of them.

After searching for a while I was able to piece some things together to get something working. In my model I added these two functions.

def thumbnailed(self, file, width, height):
    try:
        size = width, height
        tmp_file = StringIO()
        im = Image.open(StringIO(file.read()))
        im.thumbnail(size, Image.ANTIALIAS)
        im.save(tmp_file, im.format)
    except IOError:
        return None
 
    return ContentFile(tmp_file.getvalue())

Using StringIO I was able to create a temporary file in memory to hold the thumbnail data and return it where it would later be passed to django. I was trying to create 3 thumbnails which presented another problem: django was obliterating the uploaded file and the data in my temp files when I was saving. So I figured out how to get around that, but there may be better ways.

def create_thumbnails(self, file):
    pic = self.thumbnailed(file, 160, 400)
    if pic is not None:
        self.picture.save(file.name, pic, save=False)
 
    # file is annihilated by django, use self . picture now
 
    thumb = self.thumbnailed(self.picture, 288, 96)
    if thumb is not None:
        self.thumbnail.save(file.name, thumb, save=False)
 
    tiny = self.thumbnailed(self.thumbnail, 144, 48)
    if tiny is not None:
        self.tiny_image.save(file.name, tiny, save=False)

The model has picture, thumbnail, and tiny_image as ImageFields and create_thumbnails was originally called from the view and passed the uploaded file from request.FILES.

There was a lot of trial and error trying to get this together, so I hope it helps someone get past that.

PHP Developers, Keep me Sane

There has been one thing that has driven me crazy since the begining days of my php programming. I understand that using @ to suppress errors can be useful. But what I don’t understand is why php would ever want to suppress a fatal error. Normally if @function() causes a fatal error, the error will still be displayed. However, if you do @include(’file’) and there is a fatal error in that file, you get a blank page.

So if you develop in php, please try to never suppress errors from an included file. There are other ways of catching warnings and displaying your own messages, but I need those fatal errors to help me to continue developing with your software.

Just Heard About an Open-Source Database Conference

Baron Schwartz, the lead author of High Performance MySQL 2nd Edition, has just announced OpenSQL Camp 2008 over at his blog.

Despite the name, this will be different from other Camp conferences you’ve been to. This is a combination of a planned event (with great speakers and sessions), semi-planned spontaneity (sessions to be decided by attendees the night before), and a hackfest. It’s the best elements cherry-picked from all the conferences (and un-conferences) you’ve been to.

The event is in Charlottesville, Virginia on Nov 14 to 16 which is Friday to Sunday. Travel and other important information is over at the event’s site.

I don’t know if I’ll be able to make this one since I already have a few trips planned, but it sounds awesome.

Updated Theme and Comments

I ran across this skin while looking for new ones for a different blog. It happened to look similar to what I was hoping to create someday so I thought I would use it for a while. I’ve already modified a few small things to get it to look a little more to my liking, but it was overall very nice.

A while ago I posted about using Haloscan for a commenting system. There were many reasons I didn’t want to use it on here so I tested it out on a project site . A few weeks later, I heard about Disqus and it seemed to do everything I could ask for. I’ve implemented their system on Code Spatter to see how I like it. The best thing is I can stop using it and go back to wordpress comments with no hassle since they are stored in my database as well as on the disqus server.