2

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)
  });
Community
  • 1
  • 1
Kyle Truong
  • 2,545
  • 8
  • 34
  • 50

3 Answers3

10

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.

Tanmay D
  • 271
  • 3
  • 8
4

I would go for a REST service, like Django Rest Framework, and then use jquery to autopopulate the dropdowns.

If installing a REST service is a hassle, you could write a couple of views to get the data in json format...

For instance, if you have a REST service in /myapp/api, you could populate the Cars like this:

$.ajax({
    url: "/myapp/api/cars?format=json",
    dataType: "json",
    success: function( data ) {
        var makes=[];  
        for (var i in data) {
            car = data[i];
            if (makes.indexOf(car.make) < 0){ // avoid duplicate brands
                makes.push(car.make);
                $('#makeselect').append($('<option>', {
                    value: car.id,
                    text: car.make
                }));
            }
        }
    }
});

Then, attach a handler when the "make" selector has changed, and populate the model and year accordingly using another REST call, like /myapp/api/cars?make=Ford

  • BTW, i recommend to have a separate Model for car makers. That way you can get and filter the models and makers in the database (using Django queries) and avoid all the expensive array processing. – ElGranBarta Nov 04 '15 at 21:29
1

I'm not sure what you're confused about. Why would you put every car into a page? When you build a normal non-Ajax page, you pass some data - eg the slug or ID of a database object - via the URL, you query the database for that specific object, and return its data via an HTML template.

The exact same logic applies for Ajax, except that you probably don't want an HTML template; you can just return JSON, which is easy for JS to understand.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I guess what I'm confused about is the url part from : $.ajax({ type: 'get' url: '/api/orders' .... If I make the url go to my local server, it automatically has access to all the database stuff in there? – Kyle Truong Nov 04 '15 at 21:05
  • Yes. The URL goes to a Django view, which works in exactly the same way as any other Django view. – Daniel Roseman Nov 04 '15 at 21:09