Posts tagged "django"

Empty collections are valid cache data

When using Django's cache, ensure that empty collections ([], (), {}) are treated as valid cache data.

cached = cache.get(cache_key)
if cached:
    return cached

# perform expensive operation

In the above snippet, if the call to get returns an empty collection the cached result is ignored and the value is recalculated unnecessarily.

Avoid this by explicitly comparing the return value to None:

cached = cache.get(cache_key)
if cached is not None: # much better!
    return cached

Django's documentation wisely advises against caching the literal value None, and the above snippet makes it clear why this is good advice – the get method returns None when the cache does not contain an entry for the supplied key.

Testing Django apps using localhost subdomains

This turned out to be quite a bit easier than I'd imagined. Here are the things I did:

  1. I saved Dave Fowler's subdomain middleware as middleware.py in my project directory:

    class SubdomainMiddleware:
        def process_request(self, request):
            '''Parse out the subdomain from the request'''
            request.subdomain = None
            host = request.META.get('HTTP_HOST', '')
            host_s = host.replace('www.', '').split('.')
            if len(host_s) > 2:
                request.subdomain = ''.join(host_s[:-2])
    
  2. I added this to my project's MIDDLEWARE_CLASSES:

    MIDDLEWARE_CLASSES = (
        ...,
        'middleware.SubdomainMiddleware',
    )
    
  3. I edited my /etc/hosts file as per Dave's suggestion:

    127.0.0.1 test.com
    127.0.0.1 blog.test.com
    127.0.0.1 search.test.com
    

    Initially I replaced test.com with the site's domain name, but I decided that it's useful to be able to access both the live site and the test site without editing the /etc/hosts file.

    At this point I expected everything to work as advertised. Instead, I got this:

    It works!

    That would depend on one's definition of "works". I wanted my Django site to appear, which required a very simple tweak…

  4. I added the port number to the address:

    http://test.com:8000/
    

    This actually worked. :)

Freeing myself of WordPress

I wanted to simplify everything. I wanted to write posts in Markdown, not HTML. I wanted to save posts as files, not database entries. I wanted to free myself of my dependence on WordPress, PHP, and MySQL in one fell swoop.

So, Mango was born. Mango is file-based blogging software built on Django, the excellent Python web framework. I conceived Mango to scratch an itch, and I'll bet that others out there are itchy, too.

Serializing Django model instances

One might expect the following code to serialize a Django model instance:

import simplejson
simplejson.dumps(instance)

Unforunately, this raises a TypeError, as the instance is not JSON serializable. I don't understand why model instances are not serializable, but I do have a solution: define a serialization method on the instance's model.

def toJSON(self):
    import simplejson
    return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

Here's the verbose equivalent for those averse to one-liners:

def toJSON(self):
    fields = []
    for field in self._meta.fields:
        fields.append(field.name)

    d = {}
    for attr in fields:
        d[attr] = getattr(self, attr)

    import simplejson
    return simplejson.dumps(d)

_meta.fields is an ordered list of model fields which can be accessed from instances and from the model itself. _meta.fields is one of the few features not covered in Django's excellent documentation.

Get attributes of Django model or instance

What is the best way to get the attributes of a Django model or instance?

from django.db import models

class Musician(models.Model):
    first_name = models.CharField()
    last_name  = models.CharField()
    instrument = models.CharField()

One option is to use __dict__.keys():

>>> m = Musician(first_name='Norah', last_name='Jones', instrument='piano')
>>> print m.__dict__.keys()
['last_name', 'instrument', 'first_name', 'id']

Another options is to use _meta.fields:

>>> print [f.name for f in m._meta.fields]
['id', 'first_name', 'last_name', 'instrument']

This approach also works on models directly:

>>> print [f.name for f in Musician._meta.fields]
['id', 'first_name', 'last_name', 'instrument']

Advantages of using _meta.fields

  • items in returned list are correctly ordered
  • applicable to both models and instances
  • only fields are returned

The fact that only fields are returned is extremely useful. Django appears to add its own attributes to instances in certain circumstances; using _meta.fields prevents these from interfering with one's own code.

Django syntax highlighting for Coda

I love Coda. It's just so… sexy, somehow. I've just discovered Django, with which I'm fast falling in love as well. Naturally, when I came to write my first Django template I opened Coda.app and started coding.

It soon became apparent, however, that Coda does not apply syntax highlighting to Django. The solution? Juan Pablo Claude's Django and Django-template bundles for Coda.

Django syntax highlighting in Coda
Django syntax highlighting in Coda