Archive for November 2010

Rendering Django models to JSON

I recently discussed a simple template tag that allows rendering “raw” jquery templates inside a Django template, even though the syntax overlaps. A commenter asked for a Pypi package. It was such a simple template tag that I didn’t want to maintain a separate package for it, but it turns out, this tag fits in very well with the next step in the project. The short story is that the tag is now available on Pypi.

The tag is distributed with a project I called Djason (named for Django, JSON, and former Arch Linux Developer, Jason Chu, and because djson was already taken). Djason’s primary purpose is to serialize Django models to a json client format that is friendly to client libraries, especially to jquery-tmpl. It is essentially just a fork of Django Full Serializers with a patch applied, and some minor edits to simplify the output json. I install it as a Django serializer in settings.py using:

SERIALIZATION_MODULES = {
    'djason': 'djason.json'
}

And in my code:

from django.core.serializers import serialize

    content = serialize("djason", project,
            relations=["location_set", "company", "project_type"])
    return HttpResponse(content)

I’ll probably be adding some additional code to this package to fit in with my still cloudy ideas about the proper separation between client and server code. I’ll also likely be rewriting portions of the forked project to appease my personal sense of style.

Django and jquery.tmpl

Lately, I’ve been finding Django increasingly inappropriate for the web applications I develop. I have several complaints: the forms library doesn’t extend well to ajax requests, any extensive customization to the admin requires obtuse inspection of the admin source code, many admin customizations simply aren’t possible, the “reusable apps” philosophy has added a layer of complexity to a lot of things that really should not be there, there are no obvious best practices for ajax support.

In spite of all this Django is still better than other frameworks (Python or not) that I have investigated or tested. I’ve considered writing my own web framework, but I wouldn’t maintain interest in it long enough to get it off the ground. So I’m letting my complaints bounce around in the back of my mind with the hopes that I can improve Django so that it continues to work for me as a platform.

I’m currently trying to come up with a better system for ajax requests. I have nothing concrete in mind, but I’ve started with the premise that ajax requests should never return rendered html, but should return only json (hence my issue with the django forms library). With that in mind, I need a templating library for json data. JQuery is a must, and the officially supported JQuery templating library is jquery.tmpl http://api.jquery.com/category/plugins/templates/

The problem with jquery.tmpl is that it uses django-like syntax. The following is a valid block that may be rendered in a jquery.tmpl page:

<script id="project_tmpl" type="text/x-jquery-tmpl">
    {{each projects}}<li>${$value}</li>{{/each}}
</script>

If you try to include this in a django template, the {{ and }} tags will be replaced with (probably) empty variables. Django has {% templatetag %} to render these individual items, but what we really need is a way to tell the django templating system to leave complete sections of code alone. So I wrote the jqtmpl template tag. It allows us to wrap code in a block that tells Django not to render that block as template code. So the above would show up in a Django template as follows:

<script id="project_tmpl" type="text/x-jquery-tmpl">
{% jqtmpl %}
    {{each projects}}<li>${$value}</li>{{/each}}
{% endjqtmpl %}
</script>

Here’s the template tag:

from django.template import Library, TextNode, TOKEN_BLOCK, TOKEN_VAR
 
register = Library()
 
@register.tag
def jqtmpl(parser, token):
    nodes = []
    t = parser.next_token()
    while not (t.token_type == TOKEN_BLOCK and t.contents == "endjqtmpl"):
        if t.token_type == TOKEN_BLOCK:
            nodes.extend(["{%", t.contents, "%}"])
        elif t.token_type == TOKEN_VAR:
            nodes.extend(["{{", t.contents, "}}"])
        else:
            nodes.append(t.contents)
 
        t = parser.next_token()
 
    return TextNode(''.join(nodes))

This doesn’t handle Django’s {# comments #}, as token.contents doesn’t return a valid value for comment items. As far as I know, you wouldn’t use the comment construct inside a jquery.tmpl template anyway, so it’s still functional.

Next on my list is a better forms validation library to suit my theory that validation should be done client side. I’ve got a server-side system in mind that returns json responses, and does not return user-facing error messages, since those should have been caught client side. With these tools, and hopes for Grappelli to eventually create a decent admin, Django may continue to serve me.

Another release of Prickle, the stay out of your way time tracker

I just released version 0.3 of Prickle, a time tracking tool I’ve mentioned before. Prickle is a simple stay-out-of-your-way time tracking program that I find very useful for my day-to-day work as a consultant. In originally developing it, I modeled it after Freckle. With version 0.3, I consider Prickle to be more usable and more powerful than Freckle for my specific purposes. It may be useful for you as well.

The major improvement in this release is the ability to have multiple types of work for a given project. Each type is represented in the invoice by a different line-item, and can optionally have a different rate. So if you bill admin work at a different rate than development, prickle can handle it on one invoice. This required adding one more field to the log it form, which means one extra keypress for logging line items, but the new field is perfectly comfortable staying blank. It also autocompletes the types for a given project, so it is still stay-out-of-your way convenient.

The other major change is the ability to edit timesheet rows. I find this useful when I occasionally bill a timesheet for the wrong date or project. This is done using inline editing and is very ajaxy. At a user request, I’ve also changed the timesheet view to use hours and minutes rather than decimal representation.

Prickle is now working pretty much as I want it. I may add some reportlab pdf generation at some point so I can automatically e-mail pdf invoices, and a little extra customizability may be in order. The entire interface really wants some design love, but I am really hoping another user will jump up and do that. I’m not what you’d call a design guru. But overall, I think the current feature set is what I need, and I believe it may be useful for a few other people in the consulting field as well.