biais.org

Tuesday 8 January 2008

StaticGenerator for Django: create static files for lightning fast performance

StaticGenerator is a Python class for Django that makes it easy to create static files for lightning fast performance. It accepts strings (URL), Models (class or instance), Managers, and QuerySets in a simple syntax.

StaticGenerator project page

The benchmark seems very favorable for StaticGenerator against Django cached data.

Tuesday 13 November 2007

Django schema evolution (or schema migration)

django-evolution is a response to schema evolution for django models. A quote from the website:

Django Evolution is an extension to Django that allows you to track changes in your models over time, and to update the database to reflect those changes.

Notes:

  • A Wiki page on the django website discussing how to implement schema evolution.
  • Another tool for django migration: DbMigration

Tuesday 24 April 2007

Django logging

django-logging, a python module to help debugging django apps.

From their overview page:

It is really useful to know what your Django project is doing, especially when debugging. [...] Python had a built-in logging system, so django-logging was created to allow it to be easily used within Django projects. [...] When you view a page in your browser, any log messages that were created during the processing of your request will appear at the bottom of the page.

Note: a blog entry about django and logging (with comments from django devs).

Friday 6 April 2007

Warning if you use the Django development version

Warning if you use the Django development version:

we've recommended that people use the Django development version instead of the latest Django release, as we try hard to keep the development version stable. We're loosening that policy, temporarily, for the immediate future, in order to make a number of backwards-incompatible changes to the development version.

Quote from the Django Weblog

Quote from Jacob Kaplan-Moss interview on Django

Django shines when it comes to developing "content-oriented" web sites....

If you think about it, most of the really popular and big sites online are "content-oriented": YouTube, Wikipedia, Ebay, Amazon, Craigslist... it's pretty obvious to me that well organized content drives traffic. Django's main goal is to make organizing that content as painless as possible.

I'm also extremely proud of how well Django makes the transition from development to deployment. We've always kept performance and scalability at the top of our list of goals, and I think we've made out very well. There's nothing worse than developing a site only to discover that the tool you chose makes deployment or scaling impossible.

Jacob Kaplan-Moss (one of the lead developers of Django) interview

Tuesday 16 January 2007

Django generic view and performance problem

Django generic views let the developper to quickly write common pattern to create, update, delete and show objects. There is a common problem with the create / update generic view discussed on the django developpers mail list with solutions on the django wiki. Generic view create_object generates a HttpResponse from a model name. You can then write a basic template and use the form generated by the generic view.

A basic example starting with the model.py:

class Thing(models.Model):
    name = models.CharField(maxlength=100)

views.py (note you can directly write it in your urls.py file as in the django documentation):

from myapp.models import Thing
 
def create_thing(request):
    return django.views.generic.create_update.create_object(Thing, 
             template='create.html', post_save_redirect="..")

In the urls.py file:

(r'^creatething/', "myapp.views.create_thing")

In the template create.html:

<form method="post" action="">
  <p>
    <label for="id_name">Name:</label> {{ form.name }}
  </p>
  <input type="submit" />
</form>

And, that's all ! Now, we are going to update our models:

class Element(models.Model):
    name = models.CharField(maxlength=100)
 
class Thing(models.Model):
    element = models.ForeignKey(Element)
    name = models.CharField(maxlength=100)

The default behavior of the generic_view is to generate a form with a combobox to select the foreign element from a list. The problem here, if there is a lot of Element objects, django needs to get all data from the Element table and generate an enormous combobox. We are solving this problem by using the raw_id_admin option. Note: the problem go upstream to the generic view from the AutomaticManipulator.

Supposing we are creating Thing from an element_detail page.

(r'^(?P<elementname>\w+)/creatething/$', "myapp.views.create_thing")

Add the raw_id_admin option:

class Thing(models.Model):
    element = models.ForeignKey(Element, raw_id_admin=True)
    name = models.CharField(maxlength=100)

Modify the views.py

from myapp.models import Thing, Other
 
def create_thing(request, elementname):
    element = get_object_or_404(Element, name=elementname)
    return django.views.generic.create_update.create_object(Thing, 
        template='create.html', context={'element':element}, 
        post_save_redirect="..")

Modify the template:

<form method="post" action="">
  <input type="hidden" id="id_element" name="element" value="{{element.id}}" />
  <p>
    <label for="id_name">Name:</label> {{ form.name }}
  </p>
  <input type="submit" />
</form>

Ok, the performance problem for creating a new Thing is solved, but you need to find the Element before. How ?

Thursday 11 January 2007

Django custom template filters

Django template filters are like unix pipes. In this example, we want to create a filter that take a $Date$ Subversion keyword and modify the date and time string format. Note: that also work with CVS, because CVS and Subversion shares the same keyword syntax.

Create a templatetags directory in you application folder, touch a __init_.py and a file where you are going to write your filters, for this example svn_keyword_filters.py

You should have a directory tree looking like:

myapp/
    views.py
    templatetags/
        __init__.py
        svn_keyword_filters.py

In svn_keyword_filters.py write:

from django import template
register = template.Library()
 
@register.filter("svndate")
def svndate(value):
    return value[7:26]

In the template add something like:

<p>
  {% load svn_keyword_filters  %}
  {{ "$Date: 2006-11-02 11:45:14 +0100 (Thu, 02 Nov 2006) $"|svndate }}
</p>

Produces this html output

<p>
  2006-11-02 11:45:14
</p>

Check the Django documentation about custom template filters.

Saturday 6 January 2007

Django framework and complex DB request

I'm using the Django framework for my project at work. Django is really great but sometimes I have difficulties to find the "good way". Today, I discovered how to do complex lookups. Starting with this models :
from django.db import models
class Recipe:
     name = models.CharField(unique=True)
class Ingredient:
     recipe = models.ForeignKey(Recipe)
     name = models.CharField()
     quantity = models.FloatField(max_digits=5, decimal_places=2)
You're looking for all recipes containing ingredient name begining by chick or named turkey ?
from myapp.models import Recipe
from django.db.models import Q
 
Recipe.objects.filter(Q(ingredient__name__startswith="chick")\
                     |Q(ingredient__name="turkey"))
Or maybe recipes with name containing "thanks giving" and using chicken as ingredient:
Recipe.objects.filter(Q(name__icontains="thanks giving")\
                     &Q(ingredient__name="chicken"))
Read more in the Django documentation.