Джанго зависимый выбор

Я знаю, что есть много ответов на этот вопрос, но я новичок в Django, и я не знаю, как реализовать эти решения. Первое, что я хочу сделать. Это мои модели:

class Region(models.Model):

    name = models.CharField(max_length=255, verbose_name=_("Name"))
    slug = models.SlugField(max_length=150, unique=True, null=True)

    def save(self,*args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super(Region,self).save(*args,**kwargs)

    def __unicode__(self):
        return u'%s' % (self.name)

    class Meta:
        verbose_name = _('Region')
        verbose_name_plural = _('Regions')

class District(models.Model):

    name = models.CharField(max_length=255, verbose_name=_("Name"))
    slug = models.SlugField(max_length=150, unique=True, null=True)
    region = models.ForeignKey(Region,verbose_name=_("Region"))

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super(District, self).save(*args, **kwargs)

    def is_in_region(self, region):
        if self.region == region:
            return True
        else:
            return False

    def __unicode__(self):
        return u'%s' % (self.name)

    class Meta:
        verbose_name = _("District")
        verbose_name_plural = _("Districts")

На странице веб-интерфейса я хочу выбрать один регион и выбрать с районами покажет районы этого региона. Это мои взгляды:

class SearchView(ListView):

    template_name = 'advert/list_view.html'

    def all_json_models(self, request, region):
        current_reg = Region.objects.get(slug=region)
        districts = District.objects.all().filter(region=current_reg)
        json_models = serializers.serialize("json", districts)
        return http.HttpResponse(json_models, mimetype="application/javascript")

    def get(self, request, *args, **kwargs): 
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.request = request
        try:
            self.page = int(self.request.GET.get('page','1'))
        except:
            self.page = 1
        self.queryset = ""
        return super(SearchView, self).get(request, *args, **kwargs)

    def get_queryset(self):
        """We have to bypass the queryset because
        we are joining several object lists together. """
        return None

    def get_context_data(self, **kwargs):
        context['regions'] = Region.objects.all().order_by("name")
        return context

метод get_context_data намного длиннее, но я пишу здесь только простой. Я использую для этого решения с этого сайта http://www.devinterface.com/blog/en/2011/02/how-to-implement-two-dropdowns-dependent-on-each-other-using-django-and-jquery/. Но все же выбор с районами не работает. Я пытаюсь написать метод all_json_models для этого класса в представлениях, но он по-прежнему не вызывает этот метод. Есть ли кто-нибудь, кто может сказать мне, почему? Большое спасибо

3 ответа

Решение

Ну, я написал целый проект только для вас, надеюсь, это поможет:)
В этом проекте у меня есть страны, которые имеют много городов
как показано на рисунках, каждый раз, когда вы выбираете страну, в следующем поле со списком отображаются только связанные города:)

иранские города

Города США

хорошо, нет, давайте посмотрим код
(полный исходный код проекта находится на моем GitHub: https://github.com/nodet07/Django-Related-DropDowns)
models.py:
просто 2 простые модели, страна, в которой может быть много городов!

 from django.db import models
    class City(models.Model):
        name = models.CharField(max_length=50)
        country = models.ForeignKey("Country")
        def __unicode__(self):
            return u'%s' % (self.name)

    class Country(models.Model):
        name = models.CharField(max_length=50)
        def __unicode__(self):
            return u'%s' % (self.name)

views.py:

from django.shortcuts import render
from map.models import *
from django.utils import simplejson
from django.http import HttpResponse

def index(request):
    countries = Country.objects.all()
    print countries
    return render(request, 'index.html', {'countries': countries})

def getdetails(request):
    #country_name = request.POST['country_name']
    country_name = request.GET['cnt']
    print "ajax country_name ", country_name

    result_set = []
    all_cities = []
    answer = str(country_name[1:-1])
    selected_country = Country.objects.get(name=answer)
    print "selected country name ", selected_country
    all_cities = selected_country.city_set.all()
    for city in all_cities:
        print "city name", city.name
        result_set.append({'name': city.name})
    return HttpResponse(simplejson.dumps(result_set), mimetype='application/json',     content_type='application/json')

index.html:

<html>
    <head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="http://yourjavascript.com/7174319415/script.js"></script>
        <script>
            $(document).ready(function(){
                 $('select#selectcountries').change(function () {
                     var optionSelected = $(this).find("option:selected");
                     var valueSelected  = optionSelected.val();
                     var country_name   = optionSelected.text();


                     data = {'cnt' : country_name };
                     ajax('/getdetails',data,function(result){

                            console.log(result);
                            $("#selectcities option").remove();
                            for (var i = result.length - 1; i >= 0; i--) {
                                $("#selectcities").append('<option>'+ result[i].name +'</option>');
                            };


                         });
                 });
            });
        </script>
    </head>

    <body>
        <select name="selectcountries" id="selectcountries">
        {% for item in countries %}
            <option val="{{ item.name }}"> {{ item.name }} </option>    
        {% endfor %}
        </select>   


        <select name ="selectcities" id="selectcities">


        </select>

    </body>
</html>

Вы можете использовать подключаемый модуль Jquery.

Пример: http://codepen.io/anon/pen/EapNPo?editors=101

HTML

<select id="id_country" name="country">
    <option value="" selected="selected">---------</option>
    <option value="1">Colombia</option>
    <option value="2">Rusia</option>
</select>
<select id="id_city" name="city">
    <option value="" selected="selected">---------</option>
    <option value="1" class="1">Bogotá</option>
    <option value="2" class="2">Moscú</option>
    <option value="3" class="2">San Petersburgo</option>
    <option value="4" class="1">Valledupar</option>
</select>

JS

$("#id_city").chained("#id_country");

Создать форму с моделями (ForeignKey)

Перейдите на https://axiacore.com/blog/django-y-selects-encadenados/ полное руководство

Я сыт по горло решениями, не связанными с СУХОЙ, поэтому я написал что-то достаточно гибкое для большинства случаев использования:

Джанго связанных-выберите

Сейчас он обрабатывает только поля выбора, связанные с онлайн /AJAX. В конце концов я планирую (возможно, на этой или следующей неделе) добавить автономный режим, который добавляет немного визуализированного JS к виджету, чтобы отслеживать событие onchange родительского объекта и преобразовывать его в дочерние варианты с помощью карты значений -> list(выборы).). Решение AJAX отлично подходит для таких вещей, как марка / модель автомобиля (1000 вариантов выбора), а автономное решение отлично подходит для продукта / цвета (возможно, 10 вариантов выбора).

Обновленный ответ здесь для кода AJAX, а также некоторые дополнения для ясности. Снизу просто измените #selectyear на ваш выбранный идентификатор, а также переименовать переменную schedule_yearк чему-то, что имеет смысл для ваших данных. Затем измените #selectscheduleв успехе имя вашего второго идентификатора выбора. Обратите внимание, что result[i].schedule_name, соответствует имени значения, переданного обратно из представления. См. Views.py result_set и измените имена соответственно своим данным.

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

javascript и AJAX

<script>
$(document).ready(function(){
    //handle selected year
    $('select#selectyear').change(function () {
        var optionSelected = $(this).find("option:selected");
        var valueSelected  = optionSelected.val();
        var schedule_year   = optionSelected.text();
        $.ajax({
            url: 'getdetails/',
            type: 'GET',
            data: {'year' : JSON.stringify(schedule_year)},
            success:    function(result){
                            //remove previous selections
                            $("#selectschedule option").remove();
                            //add a blank option
                            $("#selectschedule").append('<option></option>');
                            //append new options returned
                            for (var i = result.length - 1; i >= 0; i--) {
                                $("#selectschedule").append('<option>'+ result[i].schedule_name +'</option>');
                            };
                        },
        });
    });
});
</script>

HTML

<table width="100%" class="table">
   <tr>
      <td class="align-middle" style="width: 50%;">
         <label for="#selectyear" value="calendar_year" style="width:100%">
            <span class="small pl-1">Select Calendar Year</span>
            <select class="form-control" name="selectyear" id="selectyear">
               <option value="blank"></option>
                  {% for schedule in schedules|dictsort:'fee_schedule_calendar_year' %}
                     {% ifchanged %}<!--used to only show unique values-->
                     <option value="{{ schedule.fee_schedule_calendar_year }}">{{ schedule.fee_schedule_calendar_year }}</option>
                     {% endifchanged %}     
                  {% endfor %}
            </select>
         </label>
      </td>
      <td class="align-middle" style="width: 50%;">
         <label for="#selectschedule" value="fee_schedule" style="width: 100%;">
         <span class="small pl-1">Select Fee Schedule</span>
            <select class="form-control" name="selectschedule" id="selectschedule"></select>
         </label>
      </td>
   </tr>
</table>

Views.py

# Handle AJAX request for fee schedule calendar year select
def getdetails(request, file_upload_id, file_header_id):
    schedule_year = json.loads(request.GET.get('year'))
    result_set = []
    schedules = FeeSchedule.objects.filter(fee_schedule_calendar_year=schedule_year)
    for schedule in schedules:
        result_set.append({'schedule_name': schedule.fee_schedule_name})
    return HttpResponse(json.dumps(result_set, indent=4, sort_keys=True, default=str), content_type='application/json')

urls.py

path('whatever_your_current_path_is_for_this_view/getdetails/', login_required(views.getdetails), name='get_details'),
Другие вопросы по тегам