Living on the Edge

Werkzeug Debugger in Django

Posted on June 21, 2008

A new feature to come to the Django-Command-Extensions project is the implementation of a new management command called runserver_plus. For now the “plus” part means that I’ve replaced the standard Django traceback pages with the Werkzeug Debugger traceback page in it’s place.

Getting Started

This item requires that you have the Werkzeug WSGI utilities installed, in addition to the django-command-extensions app.

To get started we just use the `runserver_plus` command instead of the normal `runserver` command:


$ python manage.py runserver_plus

 * Running on http://127.0.0.1:8000/
 * Restarting with reloader...
Validating models...
0 errors found

Django version 0.97-newforms-admin-SVN-unknown, using settings 'screencasts.settings'
Development server is running at http://127.0.0.1:8000/
Using the Werkzeug debugger (http://werkzeug.pocoo.org/)
Quit the server with CONTROL-C.

Note: all normal runserver options apply. In other words, if you need to change the port number or the host information, you can do so like you would normally.

Using

Whenever we hit an exception in our code, instead of the normal Django traceback page appearing, we see the Werkzeug traceback page instead.

Along with the typical traceback information we have a couple of options. These options appear when you hover over a particular traceback line. Notice that two buttons appear to the right:

The options are:

View Source

This displays the source below the traceback:

Being able to view the source file is handy because you are able to get more context information around where the error occurred. The actual traceback areas are highlighted so they are easy to spot.

One awkward piece about this is that the page is not scrolled to the bottom. At first I thought nothing was happening because of this.

Interactive Debugging Console

When you click on this button a new pane will open up below the traceback line you’re on. This is the money shot:

An ajax based console appears in the pane and you can begin debugging away. Notice in the screenshot above I did a print environ to see what was in the environment parameter coming into the function.

Summary

I’ve only been using the Werkzeug debugger on my Django projects for a day now. But I’m loving it. I encourage you to check it out. Plus if you’re not a current Django-Command-Extensions user, you’re going to find tons of really cool additions in there.

WARNING: This should never be used in any kind of production environment. Not even for a quick check into a problem. I cannot emphasize this enough. The interactive debugger allows you to evaluate python code right against the server. You’ve been warned.

FancyZoom Javascript

Posted on February 14, 2008

Cabel Sasser, co-founder of Panic Inc., just announced the release of FancyZoom v1.1. FanzyZoom is a very cool “lightbox-esque” library that zooms, fades in and out, in the same way that Quick Look works on Mac OS X.

Django Templates in Javascript

Posted on February 07, 2008

Neil Roberts implemented the Django template language in JavaScript. Pretty cool stuff. Find out more at Ajaxian

Javascript Code Highlighter

Posted on January 03, 2008

I’ve had a lot of people ask me about the syntax highlighting used on this blog site. When I was setting up this blog there were a couple of different solutions that involved plugins to Mephisto. Instead of going that route I figured there must be a javascript based solution. I found this javascript based highlighter and began to use it effortlessly. It’s not the most efficient thing but it does work well. The only modifications I made was to to the syntax coloring file to make it look more like the Vibrant Ink theme in Textmate.

YUI 2.4.0 Released

Posted on December 06, 2007

I was very excited to see that Yahoo! released version 2.4.0 of the YUI javascript framework. I’m especially excited about the selector stuff as well as the Get Utility. Get Utility is something I’ve been waiting for a long time.

I began working with YUI very early on in the release cycle. For me it was most attractive because t seemed very stable and polished and the docs have just been tremendous every step of the way. There were other frameworks at the time but they were either horribly lacking in good documentation or seemed to be a collection point for everything and anything without any real focus on stability.

The past few months I’ve been really getting into JQuery because it’s simple and intuitive interface, lightweight footprint, and excellent documentation. Although, with these recent additions to YUI I may just have to consider going back for the development of my largish, yet to be named, project I’m working on.

World of Solitaire

Posted on August 21, 2007

Amazing Ajax work, plus loads of fun.

http://worldofsolitaire.com/

Javascript Primer

Posted on August 14, 2007

As web development begins to move more client side with things like Ajax, Javascript is playing a larger role in the life of a developer. This article by Ray Djajadinata is an excellent introduction to understanding javascript. The author does a wonderful job of explaining how the javascript language works and compares it to things we already understand, such as classes, anonymous methods, etc…

Create Advanced Web Applications With Object-Oriented Techniques

JSON Generic Serializer

Posted on July 29, 2007

Recently I needed to implement some Ajax functionality into a Django app I’m building. Although Django has full support for working with Ajax and the Ajax library of your choice, out of the box it doesn’t steer you in any particular direction in this regard. Because of this I had been a bit hesitant about attacking this particular problem, fearing I would end up losing days of productivity trying to get something going. Luckily my fear was unfounded. It turns out that it’s fairly easy to implement, and quite simple to get your head around it.

One of the things I really needed was an easy way to serialize objects of data as an Ajax response back to my client. I searched around and through a combination of various forum postings and IRC, I was able to come up with the following generic json serializer. Like Generic Views, it allows me to easily make requests without a bunch of extra view code for standard cases. The implementation that I ended up with looks like this:


from django.http import HttpResponse 

def serialize(queryset, root_name=None): 
    if not root_name: 
        root_name = queryset.model._meta.verbose_name_plural 
    return '{"total": %s, "%s": %s}' % (queryset.count(), root_name, json_encode(queryset))  

def json_generic_query_serialize(request, queryset, criteria=None, parameter='query', root_name=None): 
    if criteria:
        qs = queryset.filter(**{'%s' % criteria: request[parameter]})
    else:
        qs = queryset
    return HttpResponse(serialize(qs, root_name=root_name), mimetype='text/javascript')

The only item you’re not likely to have is the method json_encode by Wolfram Kriesing. Believe it or not I found this tidbit on a dpaste post and it was exactly what I needed. Later I found out that Wolfram blogged about this item on his website. I encourage you to read his reasons for writing this nice tidbit.

The reason the default json serializer (django.core.serialize) doesn’t work well for my purposes is because the default implementation is built around the idea that the objects that are serializable need to be deserializable as full objects as well. I’m using the Yahoo! User Interface Library as my Ajax library and YUI will not work well with the default json structure provided by Django.

Just in case the json_encode method gets removed from dpaste I’m reprinting it here. I want to stress again that this is the work of Wolfram Kriesing, not mine. I included this method in the same file as my serializer methods posted above.


import types
from django.db import models
from django.utils import simplejson as json
from django.core.serializers.json import DateTimeAwareJSONEncoder
from decimal import *

def json_encode(data):
    """ 
    The main issues with django's default json serializer is that properties that
    had been added to a object dynamically are being ignored (and it also has 
    problems with some models).
    """ 

    def _any(data):
        ret = None
        if type(data) is types.ListType:
            ret = _list(data)
        elif type(data) is types.DictType:
            ret = _dict(data)
        elif isinstance(data, Decimal):
            # json.dumps() cant handle Decimal
            ret = str(data)
        elif isinstance(data, models.query.QuerySet):
            # Actually its the same as a list ...
            ret = _list(data)
        elif isinstance(data, models.Model):
            ret = _model(data)
        else:
            ret = data
        return ret

    def _model(data):
        ret = {}
        # If we only have a model, we only want to encode the fields.
        for f in data._meta.fields:
            ret[f.attname] = _any(getattr(data, f.attname))
        # And additionally encode arbitrary properties that had been added.
        fields = dir(data.__class__) + ret.keys()
        add_ons = [k for k in dir(data) if k not in fields]
        for k in add_ons:
            ret[k] = _any(getattr(data, k))
        return ret

    def _list(data):
        ret = []
        for v in data:
            ret.append(_any(v))
        return ret

    def _dict(data):
        ret = {}
        for k,v in data.items():
            ret[k] = _any(v)
        return ret

    ret = _any(data)

    return json.dumps(ret, cls=DateTimeAwareJSONEncoder)

Once the generic serializer is in place, it becomes easy to use. We need an entry in our urls.py file that routes the Ajax request to our generic serializer. A typical implementation will look like this:


categories_dict = { 
    'queryset': Category.objects.all(), 
    'root_name': 'categories',
    'criteria': 'name__icontains',  
} 

urlpatterns += patterns('', 
    (r'json/categories/', json_generic_query_serialize, categories_dict), 
)

Notice how flexible this implementation is. We can pass any criteria we want for finding our items. If we wanted to simply return all items, we would only need the ‘queryset’ item.

So what does this look like in the Form definition in our Forms.py file? It depends on what we want to accomplish. As an example, I’m implementing an AutoComplete field from the Yahoo! User Interface Library. My implementation looks like this:


category = forms.CharField(max_length=255, 
                           label=u'Category', 
                           widget=AutoCompleteField(source='/blog/json/categories/', 
                           schema=["categories", "name", "id"], 
                           options={ 'animSpeed': 0.1, 'autoHighlight': True, 'forceSelection': True, 'typeAhead': True }))

In the above sample I’m using a custom AutoCompleteField widget that I created that gives me all of the auto complete goodness that I need. I’ll write more about the implementation of that custom widget field in another blog post.

As you can see, solving the problem of easily getting serialized data in json format makes the whole Ajax process much simpler. Although Ruby on Rails bakes this functionality into the framework at times it becomes a two edged sword. It sure makes it easy for new users to start using Ajax immediately with little or no knowledge, but it also makes it quite painful to use any Ajax library that has not been “anointed.” I have no person preference of one implementation over the other, it’s just important to recognize the advantages and disadvantages of differing approaches.

Yahoo! Hosts YUI Files

Posted on February 28, 2007

To coincide with the new release of Yahoo YUI Javascript library, and one year anniversary, Yahoo! has decided to provide hosting of all the YUI files, include old versions of the Javascript libraries. This means high reliability and increased speed from serving up compressed versions of the files to all users.

Free YUI Hosting