Fork me on GitHub

LaunchYard logo
Sneakernet ! Reliable network
The outdated Web blog of a software engineer. →

Using django-chosen with dynamic values

A couple of days ago I was searching for a JavaScript component to handle tags such as the one in StackOverflow which looks something like that:

StackOverflow Tags example

You can also think of it looking like the Facebook or Google+ autocomplete text inputs.

Chosen and django-chosen

So, googling around, I found this awesome jQuery and Prototype plugin named Chosen.

Chosen is awesome and I don't why I didn't discover it before. But there's more, for Django developers, I found (very easily, but it definitely worth a search) django-chosen.

django-chosen is a project that makes available django FormFields that uses the Chosen javascript plugin. It was created by developers at The Atlantic.

So thanks you The Atlantic developers. The README doc is good enough to start working. But if you want your values to be dynamically loaded, like me, e.g. the list of friends of a specific user for instance, where's what you can do.

Dynamic FormField values

At first I tried to fill the choices param, but for some reasons, I failed, so here's another solution.

In your form, override the __init__ function of you Form class. Here I used an instance of DocumentForm because I'm using CouchDB and couchdbkit, but its the same.

from django import forms
from couchdbkit.ext.django.forms import DocumentForm
from chosen import forms as chosenforms
from myapp.models import Invite

class InviteForm(DocumentForm):
    name = forms.CharField(required=True, max_length=15, min_length=5, widget=forms.widgets.TextInput())

    def __init__(self, *args, **kwargs):
        buddies = kwargs.pop('buddies')
        super(InviteForm, self).__init__(*args, **kwargs)
        self.fields['buddies'] = chosenforms.ChosenMultipleChoiceField(required=True, overlay='Select some friends...', choices=buddies)

    class Meta:
        document = Invite

Now, in the view, get your data, and pass it to your form.

def invite_buddies(self):
    ...
    # Here I retrieve the buddies via a CouchDB view and convert it to a tuple of tuples as
    # the example of the django-chosen README
    buddies = get_buddies_from_somewhere()
    if request.method == 'POST':
        form = InviteForm(request.POST, buddies=buddies)
        if fo.is_valid():
            ...
    else:
        form = InviteForm(initial={'name':username}, buddies=buddies)
        # note that initial is not required for it to work, its just another tips to pass
        # data to your other fields

    ...

Et voilĂ !

Don't forget to add the CSS and JS file from Chosen into your template <head> tag, then call $(".chzn-select").chosen(); as is it indicated in the Chosen documentation page, and you're ready to go!

Here's my result:

my tags example

Enjoy coding ;)