2016-07-11 4 views
0

Мне нужно реализовать два раскрывающихся списка, значение которых зависит от выбора первого.Невозможно реализовать динамический раскрывающийся список в Django

Я смог реализовать это в бэкэнде, но я изо всех сил стараюсь сделать это в интерфейсе и, более конкретно, с помощью javascript!

countries = Country.objects.filter(Enabled=True) 
citiesByCountry = {} 

for country in countries: 
    citiesInCountry = City.objects.filter(Enabled=True, Country=country) 
    cities = [] 

    for city in citiesInCountry: 
     cities.append(city.Name) 

    citiesByCountry[country.Name] = cities 

context = {'citiesByCountry': citiesByCountry} 
return render(request, 'index.html', context) 

Так я следующая структура:

'Country':['City1', 'City2'] 

Вот HTML:

<div class="form-group col-md-4"> 
    <select class="form-control" onchange="test(this.value)" id="sel1"> 
     {% for country in citiesByCountry %} 
      <option value="{{ country }}">{{ country }}</option> 
     {% endfor %} 
    </select> 
</div> 
<div class="form-group col-md-4"> 
    <select class="form-control" id="cities"> 
    </select> 
</div> 

Так я добавил следующие Javascript:

<script> 
    var country_objs = {}; 
    {% for country, cities in citiesByCountry.items %} 
     country_objs['{{country|escapejs}}'] = '{{cities|escapejs}}'; 
    {% endfor %} 
</script> 

<script type="application/javascript"> 
    function test(country) { 
     var $cities_select = $("#cities"); 
     $(country_objs[country]).each(function(){ 
      $cities_select.append('<option>' + this + '<\option>'); 
     }); 
    } 
</script> 

Второй выпадающее меню никогда не заполняется d, но когда я печатаю содержание country_objs как это: console.log(country_objs[country]);

Я получаю следующее:

['City1', 'City2', 'City3'] 

Который является правильным, но функция .each не делает петлю по пунктам. Я думаю, проблема в том, что выше это не правильный массив, а строка, но до сих пор не могу понять, почему.

Обратите внимание, что я получаю следующее сообщение об ошибке:

jquery.min.js:2 Uncaught Error: Syntax error, unrecognized expression: ['City1', 'City2', 'City3'] 

К сожалению, все, что я стараюсь не работать, я не мог себе представить, что реализация этого в Django будет так трудно.

Я хотел бы избежать использования стороннего приложения или модуля для выполнения этой простой задачи, и я хотел бы использовать правильный способ сделать это (наилучшим образом), чтобы любые идеи были действительно полезными.

ответ

1

Есть два решения:

Решение 1:

использование для цикла:

country_objs['{{country|escapejs}}'] = [{% for city in cities %}"city",{% endfor %}]; 

Раствор 2:

Переключатель линия:

citiesByCountry[country.Name] = cities 

для:

citiesByCountry[country.Name] = json.dumps(cities) 

кодировать JSON, а затем в шаблоне:

country_objs['{{country|escapejs}}'] = {{cities|safe}}; 

Obs относительно решения 2:

Вы не можете иметь одинарные котировки вокруг переменной

'{{cities|safe}}'; 

во втором растворе, либо при добавлении в список ['City1', 'City2', 'City3'] ты собираешься иметь:

'['City1', 'City2', 'City3']' 
+0

Работали !! Спасибо! Единственная проблема заключается в том, что в моем раскрывающемся списке моих городов есть несколько пустых строк в качестве опций среди фактических городов, которые я не уверен, откуда они пришли. – John

+0

no prob :) Если вы печатаете список в python, нет пустых строк? Кроме того, не забудьте установить значение optinos в городах, а также – dietbacon

+0

Нет нет пробелов в списке python, и я также задал значение. – John

0

Я думаю, что вы хотите удалить |escapejs фильтр для части, которую вы хотите быть проанализирован в JavaScript , Возможно, вам даже понадобится |safe, но вы должны быть уверены, что у вас есть контроль над тем, что будет выводиться там, прежде чем рассматривать это.

var country_objs = {}; 
{% for country, cities in citiesByCountry.items %} 
country_objs['{{country|escapejs}}'] = {{cities|safe}}; 
{% endfor %} 

Для обновления части, это должно работать:

function updateCities(country) { 
    var $cities_select = $("#cities"); 
    $(country_objs[country]).each(function(key, value) { 
     $('#cities').append($("<option></option>") 
        .attr("value",key) 
        .text(value)); 
    }); 
} 

$('#sel1').change(function() { 
    updateCities(this.value); 
}); 

кредит частично благодаря этому ответу https://stackoverflow.com/a/171007/823020.

В приведенной выше форме отсутствует начальная настройка, которую вы можете использовать в шаблонах или JavaScript. Для JavaScript вы можете вставить еще один номер updateCities($('#cities).val());.

Вышеуказанное также добавляется каждый раз, вместо того, чтобы сбросить параметры в пустой список. Это остается как упражнение для читателя.

Предложение 1: Вы не обсуждали это, но ваш первоначальный запрос будет лучше сделать что-то вроде этого:

# the following may differ based on your foreign key's related_name attribute 
countries = Country.objects.filter(Enabled=True).select_related('city_set') 
for country in countries: 
    citiesInCountry = country.city_set.values_list('name', flat=True) 

Это все будет один запрос. Однако вам нужно переосмыслить об «активном» флаге или о том, как достичь этого, если вам все еще нужно.

Предложение 2: Если честно, возможно, лучше вообще обернуть его в json.По вашему мнению:

import json 
countries_json = json.dumps(citiesByCountry) 

, а затем в шаблоне:

var country_objs = {{ citiesByCountry|safe }}; 
Смежные вопросы