1. Skip to navigation
  2. Skip to content

Entries tagged “ajax”

Werkzeug Debugger in Django

written by Michael Trier, on Jun 21, 2008 10:37:00 PM.

A new feature to come to the 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.

Online Rails Development

written by Michael Trier, on Jan 3, 2008 10:43:00 PM.

A few weeks ago I stumbled across Heroku, an online IDE for instant Rails development. It provides editing, sharing, and collaborating of projects, as well as the ability to import and export projects.

Heroku is an amazing implementation of technology and innovative in so many ways. Even if you’re not a Rails developer you will appreciate the beauty of Heroku.

Hmm, what would it take to get something like this for Django?

YUI 2.4.0 Released

written by Michael Trier, on Dec 6, 2007 9:22:00 AM.

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.

Bayeux and Comet

written by Michael Trier, on Dec 5, 2007 9:11:00 PM.

Simon Willison has an excellent writeup on using Comet, the ajax push technology, and specifically the Bayeux protocol, a standard protocol for clients to communicate with a dedicated server. There’s been a dearth of information on comet and related technologies, so it is great to see what Simon has put together. I only wish I could have attended the talk.

World of Solitaire

written by Michael Trier, on Aug 21, 2007 1:05:00 PM.

Amazing Ajax work, plus loads of fun.

http://worldofsolitaire.com/

JSON Generic Serializer

written by Michael Trier, on Jul 29, 2007 10:25:00 PM.

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 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.