Django/jQuery, Располагающий каскадом Избранные Поля?

Я хочу создать селектор Страны/Состояния. Сначала Вы выбираете страну, и Штаты для той страны отображены в 2-м избранном поле. Выполнение этого в PHP и jQuery довольно легко, но я нахожу, что формы Django немного строги в этом смысле.

Я мог установить поле State, чтобы быть пустым на загрузке страницы и затем заполнить его с некоторым jQuery, но затем если существуют ошибки формы, это не сможет "помнить", какое состояние Вы выбрали. Я также вполне уверен, что это бросит ошибку проверки, потому что Вашим выбором не был один из тех перечисленных в форме на стороне Python вещей.

Таким образом, как я обхожу эти проблемы?

12
задан mpen 13 July 2010 в 02:46
поделиться

2 ответа

Вы можете установить скрытое поле для реального значения "state", затем использовать jQuery для создания списка после его заполнения.

Ключевой концепцией здесь является то, что всплывающее меню State - это фикция, созданная полностью на jQuery, а не часть формы Django. Это дает вам полный контроль над ним, в то же время позволяя всем остальным полям работать нормально.

EDIT: Есть и другой способ сделать это, но он не использует классы формы Django.

В представлении:

context = {'state': None, 'countries': Country.objects.all().order_by('name')}
if 'country' in request.POST:
    context['country'] = request.POST['country']
    context['states'] = State.objects.filter(
        country=context['country']).order_by('name')
    if 'state' in request.POST:
        context['state'] = request.POST['state']
else:
    context['states'] = []
    context['country'] = None
# ...Set the rest of the Context here...
return render_to_response("addressform.html", context)

Затем в шаблоне:

<select name="country" id="select_country">
    {% for c in countries %}
    <option value="{{ c.val }}"{% ifequal c.val country %} selected="selected"{% endifequal %}>{{ c.name }}</option>
    {% endfor %}
</select>

<select name="state" id="select_state">
    {% for s in states %}
    <option value="{{ s.val }}"{% ifequal s.val state %} selected="selected"{% endifequal %}>{{ s.name }}</option>
    {% endfor %}
</select>

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

Я не тестировал это, так что, возможно, в этом есть пара дыр, но идея должна быть понятна.

Итак, ваши варианты:

  • Использовать скрытое поле в форме Django для реального значения, а меню выбора создавать на стороне клиента через AJAX, или
  • Выкинуть Django's Form stuff и инициализировать меню самостоятельно.
  • Создать пользовательский виджет формы Django, чего я не делал и поэтому не буду комментировать. Я понятия не имею, можно ли это сделать, но похоже, что вам понадобится пара Selectов в MultiWidget, причем последний недокументирован в обычной документации, так что вам придется читать исходники.
8
ответ дан 2 December 2019 в 07:02
поделиться

Основываясь на предложении Майка:

// the jQuery
$(function () {
        var $country = $('.country');
        var $provInput = $('.province');
        var $provSelect = $('<select/>').insertBefore($provInput).change(function() {
                $provInput.val($provSelect.val());      
        });
        $country.change(function() {
                $provSelect.empty().addClass('loading');
                $.getJSON('/get-provinces.json', {'country':$(this).val()}, function(provinces) {
                        $provSelect.removeClass('loading');
                        for(i in provinces) {
                                $provSelect.append('<option value="'+provinces[i][0]+'">'+provinces[i][1]+'</option>');
                        }
                        $provSelect.val($provInput.val()).trigger('change');
                });
        }).trigger('change');
});

# the form
country = CharField(initial='CA', widget=Select(choices=COUNTRIES, attrs={'class':'country'}))
province = CharField(initial='BC', widget=HiddenInput(attrs={'class':'province'}))

# the view
def get_provinces(request):
    from django.utils import simplejson
    data = {
        'CA': CA_PROVINCES,
        'US': US_STATES
    }.get(request.GET.get('country', None), None)
    return HttpResponse(simplejson.dumps(data), mimetype='application/json')
0
ответ дан 2 December 2019 в 07:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: