Django, Ajax and HTML Select

This happens all the time; one field in a form determines the options in another select field. One way to handle this is to do a Ajax post. It’s not difficult, but there are lots of parts to remember. Here is one way to do it (using jquery).

The Django Ajax handler:

from django.http import JsonResponse

def get_options(request):
    project_id = int(request.POST['project_id'])
    project = models.Project.objects.get(id=project_id)

    choices = get_select_choices(project)
    options = []
    for choice_id, choice_label in choices:
        option = '<option value="{}">{}</option>'.format(str(choice_id), choice_label)
    return JsonResponse({'options': options})

The javascript

<script type="text/javascript">
    var project_field, phase_select;

    var get_phases_for_project = function(){
        var project = project_field.val();

        if (project === ""){
            "{% url 'my_url' %}",
            {project_id: project, csrfmiddlewaretoken: '{{ csrf_token }}'},
             * @param data
             * @param data.phases
                $.each(data.phases, function (index2, value) {

        project_field = $('#id_project');
        phase_select = $("#id_phase");

Grouping Choices in a Django Select

To make an ordinary Django ChoiceField you can do something like this:

choices = [[1, 'Apples'], [2, 'Oranges'], [3, 'Carrots'], [4, 'Beans']]
my_choices = forms.ChoiceField(choices=choices)

But what if you want to group the choices by using the HTML OPTGROUP tag? My first thought was to over-ride some on the methods in the Django Select widget code. But when I inspected the code, I found the code already supports this (Django 1.8). Here is how to do it:

choices = [
    ['Fruit', [[1, 'Apples'], [2, 'Oranges']]], 
    ['Veggies', [[3, 'Carrots'], [4, 'Beans']]]
my_choices = forms.ChoiceField(choices=choices)