How can Ajax work with a dynamic Django dropdown list?

Kyle Truong picture Kyle Truong · Nov 4, 2015 · Viewed 10.1k times · Source

I'm making this little web app that takes 2 addresses, calculates the distance using google maps, and calculates the gas cost based on the vehicles mpg rating. Everything is complete except for this last part that I believe would work best with AJAX.

I have 3 lists (year, make, model), and I need the list of car models to be restricted based on the year and make of the car. After selecting, I have a button that once clicked, will verify if it is a valid vehicle in the database and pull the vehicle's mpg rating to do some basic math on it.

The problem is I don't really know how to approach this problem. I've searched some inquiries the past few hours and I'm getting a lot of things related to model forms and Django choice fields which I don't want to get into if I don't have to. My idea is to just change the innerText/value, and check it against my django database.

I also came across this answer from SO:

How do I integrate Ajax with Django applications?

and am a bit confused by it. If I understand correctly, the AJAX GET request will extract data in javascript objects the same as if I visited that url as a user. Does this mean I could just create another html template and post every vehicle in the database onto that page from which I can extract info and create my dynamic lists from?

Looking for the most straightforward way to dynamically generate my lists with ajax and verify the year, make, and model with my database which will then return the car's mpg.

models.py:

class Car(models.Model):
    year = models.IntegerField(default=0)
    make = models.CharField(max_length=60)
    model = models.CharField(max_length=60)
    mpg = models.IntegerField(default=0)


    def __str__(self):
        return ("{0} {1} {2}".format(self.year, self.make, self.model))

views.py: (right now, it just lists every vehicle and has no way to verify the vehicle on the spot)

def index(request):

    context_dic = {}
    car_list = Car.objects.order_by('make')
    car_list_model = Car.objects.order_by('model')
    context_dic['car_list'] = car_list
    context_dic['years'] = []
    context_dic['makes'] = []
    context_dic['models'] = []

    for year in range(1995, 2016):
        context_dic['years'].append(year)

    for make in car_list:
        if make.make not in context_dic['makes']:
            context_dic['makes'].append(make.make)
        else:
            continue

    for model in car_list_model:
        if model.model not in context_dic['models']:
            context_dic['models'].append(model.model)
        else:
            continue

    return render(request, 'ConverterApp/index.html', context_dic)

html: (x3 for the make and model)

<div id="specifics">
    <div class="dropdown" id="year-dropdown">
      <button class="btn btn-default dropdown-toggle" type="button"
      id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
        Year
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
    {% for year in years %}
      <li><a href="#">{{ year }}</a></li>
    {% endfor %}
  </ul>
</div>

javascript: (just shows the value right now, but can't verify with the database)

  $('#calculate').on('click', function ()
  {
    $(this).siblings()[0].textContent = (
      document.getElementById("dropdownMenu1").textContent
      + " " + document.getElementById("dropdownMenu2").textContent
       + " " + document.getElementById("dropdownMenu3").textContent
       + " " + document.getElementById("specifics-gas").value
    )
  });
});

  //this part changes the year, make, model to what the user selects //from the list
  $('li').on('click', function () {
    $(this).parent().siblings()[0].innerHTML = this.innerHTML
    //console.log(this.textContent)
  });

Answer

Tanmay D picture Tanmay D · Apr 10, 2018

Suppose you have to populate a static list of all the brand names in a drop-down and the second dropdown is supposed to be populated based on the selection in first.

Assuming two simple Django models defining Brands and Showrooms.

Views.py

class YourView(TemplateView):
    template_name = 'template.html'

    def get_context_data(self, **kwargs):
        brands = Brands.objects.all()
        context = super(YourView, self).get_context_data(**kwargs)
        context.update({'brands': brands})
        return context

def get_showrooms(request, **kwargs):
    brand = Brands.objects.get(id=kwargs['brand_id'])
    showroom_list = list(brand.showrooms.values('id', 'name'))

    return HttpResponse(simplejson.dumps(showroom_list), content_type="application/json"

HTML

<label>Select Brand</label>
      <select id="brands" name="brands" class="form-control">
        <option value="">Select Brand</option>                    
        {% for brand in brands %}
          <option id="{{ brand.id }}" value="{{ brand.id }}">
                {{ brand.name }}
          </option>
        {% endfor %}
       </select>

<label>Select Showrroom</label>
    <div id="showroom_list">
      <select name="showrooms"  class="form-control">
      </select>
    </div

Ajax

$('select[name=brands]').change(function(){
    brand_id = $(this).val();
    request_url = '/sales/get_showrooms/' + brand_id + '/';
        $.ajax({
            url: request_url,
            success: function(data){
            $.each(data, function(index, text){
                $('select[name=showrooms]').append(
                $('<option></option>').val(index).html(text)
                );
              };
           });

You can make the RESTful calls in request_url.

You can further populate the third dropdown based on the selection in second and so on. Also, you can access the selected option and perform the further stuff. The chosen plugin can help you in optimizing your dropdowns.