Ajax 如何与动态 Django 下拉列表一起工作?

Posted

技术标签:

【中文标题】Ajax 如何与动态 Django 下拉列表一起工作?【英文标题】:How can Ajax work with a dynamic Django dropdown list? 【发布时间】:2016-02-05 12:24:28 【问题描述】:

我正在制作这个小网络应用程序,它需要 2 个地址,使用谷歌地图计算距离,并根据车辆 mpg 等级计算汽油成本。除了我认为最适合 AJAX 的最后一部分之外,一切都已完成。

我有 3 个列表(年份、品牌、型号),我需要根据汽车的年份和品牌来限制车型列表。选择后,我有一个按钮,一旦单击,将验证它是否是数据库中的有效车辆并拉出车辆的 mpg 等级以对其进行一些基本的数学运算。

问题是我真的不知道如何解决这个问题。在过去的几个小时里,我搜索了一些查询,我得到了很多与模型表单和 Django 选择字段相关的东西,如果我不需要的话,我不想进入。我的想法是只更改 innerText/值,然后对照我的 django 数据库进行检查。

我也从 SO 那里看到了这个答案:

How do I integrate Ajax with Django applications?

我对此有点困惑。如果我理解正确,AJAX GET 请求将提取 javascript 对象中的数据,就像我以用户身份访问该 url 一样。这是否意味着我可以创建另一个 html 模板并将数据库中的每辆汽车发布到我可以从中提取信息并创建动态列表的页面上?

寻找最直接的方法来使用 ajax 动态生成我的列表,并使用我的数据库验证年份、品牌和型号,然后返回汽车的 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:(目前只是列出每辆车,无法现场验证车辆)

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)

<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:(现在只显示值,但无法与数据库验证)

  $('#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)
  );

【问题讨论】:

【参考方案1】:

假设您必须在下拉列表中填充所有品牌名称的静态列表,并且应该根据第一个选择来填充第二个下拉列表。

假设有两个简单的 Django 模型定义了 BrandsShowrooms。

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)
                );
              ;
           );

您可以在 request_url 中进行 RESTful 调用。

您可以根据第二个中的选择进一步填充第三个下拉列表,依此类推。此外,您可以访问所选选项并执行其他操作。 chosen plugin 可以帮助您优化下拉菜单。

【讨论】:

【参考方案2】:

我会使用 REST 服务,例如 Django Rest Framework,然后使用 jquery 自动填充下拉列表。

如果安装 REST 服务很麻烦,您可以编写几个视图来获取 json 格式的数据...

例如,如果您在 /myapp/api 中有一个 REST 服务,您可以像这样填充 Cars:

$.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
                ));
            
        
    
);

然后,在“make”选择器发生变化时附加一个处理程序,并使用另一个 REST 调用(如 /myapp/api/cars?make=Ford)相应地填充模型和年份。

【讨论】:

顺便说一句,我建议为汽车制造商提供单独的模型。这样您就可以获取和过滤数据库中的模型和制造商(使用 Django 查询)并避免所有昂贵的数组处理。【参考方案3】:

我不确定你对什么感到困惑。为什么要把每辆车都放在一个页面中?当您构建一个普通的非 Ajax 页面时,您通过 URL 传递一些数据——例如数据库对象的 slug 或 ID,查询该特定对象的数据库,并通过 HTML 模板返回其数据。

完全相同的逻辑也适用于 Ajax,只是您可能不需要 HTML 模板;可以直接返回JSON,JS很容易理解。

【讨论】:

我想我很困惑的是 url 部分来自: $.ajax( type: 'get' url: '/api/orders' .... 如果我让 url 去到我的本地服务器,它会自动访问那里的所有数据库内容? 是的。该 URL 转到 Django 视图,其工作方式与任何其他 Django 视图完全相同。

以上是关于Ajax 如何与动态 Django 下拉列表一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中使用 Ajax JQuery 调用下拉列表 html 选择

django & ajax 依赖的 html 选择列表(级联下拉列表)

如何将 javascript 与 asp.net 下拉列表控件一起使用?

Codeigniter与AJAX动态相关的下拉列表

无法让 Materialize css 下拉列表与动态加载的模式一起使用

我如何在Joomla中使用Ajax! Mplayer下拉列表P3而不是iframe下拉列表的网站?