[Solved]-Django dependent select

28👍

well , i coded a whole project just for you , hope this could help 🙂 :
in this project i we have countries which have many cities
as shown in pictures, each time you select a country , only related cities shown in next combo box 🙂

iran's cities

USA's cities

ok , no let’s see the code
(full project source code is on my github : https://github.com/nodet07/Django-Related-DropDowns)
models.py :
just 2 simple models , a country which can have many cities !

 from django.db import models
    class City(models.Model):
        name = models.CharField(max_length=50)
        country = models.ForeignKey("Country")
        def __unicode__(self):
            return u'%s' % (self.name)

    class Country(models.Model):
        name = models.CharField(max_length=50)
        def __unicode__(self):
            return u'%s' % (self.name)

views.py:

from django.shortcuts import render
from map.models import *
from django.utils import simplejson
from django.http import HttpResponse

def index(request):
    countries = Country.objects.all()
    print countries
    return render(request, 'index.html', {'countries': countries})

def getdetails(request):
    #country_name = request.POST['country_name']
    country_name = request.GET['cnt']
    print "ajax country_name ", country_name

    result_set = []
    all_cities = []
    answer = str(country_name[1:-1])
    selected_country = Country.objects.get(name=answer)
    print "selected country name ", selected_country
    all_cities = selected_country.city_set.all()
    for city in all_cities:
        print "city name", city.name
        result_set.append({'name': city.name})
    return HttpResponse(simplejson.dumps(result_set), mimetype='application/json',     content_type='application/json')

index.html :

<html>
    <head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="http://yourjavascript.com/7174319415/script.js"></script>
        <script>
            $(document).ready(function(){
                 $('select#selectcountries').change(function () {
                     var optionSelected = $(this).find("option:selected");
                     var valueSelected  = optionSelected.val();
                     var country_name   = optionSelected.text();


                     data = {'cnt' : country_name };
                     ajax('/getdetails',data,function(result){

                            console.log(result);
                            $("#selectcities option").remove();
                            for (var i = result.length - 1; i >= 0; i--) {
                                $("#selectcities").append('<option>'+ result[i].name +'</option>');
                            };


                         });
                 });
            });
        </script>
    </head>

    <body>
        <select name="selectcountries" id="selectcountries">
        {% for item in countries %}
            <option val="{{ item.name }}"> {{ item.name }} </option>    
        {% endfor %}
        </select>   


        <select name ="selectcities" id="selectcities">


        </select>

    </body>
</html>

2👍

You can use Jquery plugin chained.

Example:
http://codepen.io/anon/pen/EapNPo?editors=101

HTML

<select id="id_country" name="country">
    <option value="" selected="selected">---------</option>
    <option value="1">Colombia</option>
    <option value="2">Rusia</option>
</select>
<select id="id_city" name="city">
    <option value="" selected="selected">---------</option>
    <option value="1" class="1">Bogotá</option>
    <option value="2" class="2">Moscú</option>
    <option value="3" class="2">San Petersburgo</option>
    <option value="4" class="1">Valledupar</option>
</select>

js

$("#id_city").chained("#id_country");

Generate form with models (ForeignKey)

Go to https://axiacore.com/blog/django-y-selects-encadenados/ complete tutorial

1👍

I got fed up with the non-DRY solutions to this, so I wrote something maybe flexible enough for most use cases:

django-related-select

Right now it only handles online/AJAX related select boxes. I eventually plan (maybe this week or next) to add an offline mode that pushes a bit of rendered JS with the widget to track the onchange event of the parent and translate it to the child choices via a map of value -> list(choices). The AJAX solution is great for things like car make/model (1000s of choices) while the offline solution is great for product/color (maybe 10s of choices).

👤ZachM

0👍

An updated answer here for AJAX code, as well as some additions for clarity. From the below, just change #selectyear to your select id, as well as rename variable schedule_year to something that makes sense for your data. Then change #selectschedule in success to the name of your second select id. note that result[i].schedule_name, corresponds to the name of the value passed back from the view. See views.py result_set and change names accordingly for your data.

If you are looking to implement more than 2 chained selects, it is simple. Just duplicate the code below chaining each sequence together for as many relationships needed. Reuse the same view with conditional statements or just add another view that returns new results.

javascript and AJAX

<script>
$(document).ready(function(){
    //handle selected year
    $('select#selectyear').change(function () {
        var optionSelected = $(this).find("option:selected");
        var valueSelected  = optionSelected.val();
        var schedule_year   = optionSelected.text();
        $.ajax({
            url: 'getdetails/',
            type: 'GET',
            data: {'year' : JSON.stringify(schedule_year)},
            success:    function(result){
                            //remove previous selections
                            $("#selectschedule option").remove();
                            //add a blank option
                            $("#selectschedule").append('<option></option>');
                            //append new options returned
                            for (var i = result.length - 1; i >= 0; i--) {
                                $("#selectschedule").append('<option>'+ result[i].schedule_name +'</option>');
                            };
                        },
        });
    });
});
</script>

HTML

<table width="100%" class="table">
   <tr>
      <td class="align-middle" style="width: 50%;">
         <label for="#selectyear" value="calendar_year" style="width:100%">
            <span class="small pl-1">Select Calendar Year</span>
            <select class="form-control" name="selectyear" id="selectyear">
               <option value="blank"></option>
                  {% for schedule in schedules|dictsort:'fee_schedule_calendar_year' %}
                     {% ifchanged %}<!--used to only show unique values-->
                     <option value="{{ schedule.fee_schedule_calendar_year }}">{{ schedule.fee_schedule_calendar_year }}</option>
                     {% endifchanged %}     
                  {% endfor %}
            </select>
         </label>
      </td>
      <td class="align-middle" style="width: 50%;">
         <label for="#selectschedule" value="fee_schedule" style="width: 100%;">
         <span class="small pl-1">Select Fee Schedule</span>
            <select class="form-control" name="selectschedule" id="selectschedule"></select>
         </label>
      </td>
   </tr>
</table>

Views.py

# Handle AJAX request for fee schedule calendar year select
def getdetails(request, file_upload_id, file_header_id):
    schedule_year = json.loads(request.GET.get('year'))
    result_set = []
    schedules = FeeSchedule.objects.filter(fee_schedule_calendar_year=schedule_year)
    for schedule in schedules:
        result_set.append({'schedule_name': schedule.fee_schedule_name})
    return HttpResponse(json.dumps(result_set, indent=4, sort_keys=True, default=str), content_type='application/json')

urls.py

path('whatever_your_current_path_is_for_this_view/getdetails/', login_required(views.getdetails), name='get_details'),
👤JSS

Leave a comment