Выпадающие меню страны/Состояния/Города во встроенном администраторе Django

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

9
задан Glorfindel 5 May 2019 в 19:05
поделиться

3 ответа

С маленьким бутиком, это довольно выполнимо.

В следующем примере используется Состояние и муниципалитета вместо города . Таким образом, модели являются следующими:

class County(models.Model):
    name = models.CharField(_('Name'), max_length=100, unique=True)

class Municipality(models.Model):
    county = models.ForeignKey(County, verbose_name=_('County'))
    name = models.CharField(_('Name'), max_length=100)

class Location(models.Model):
    name = models.CharField(max_length=100)
    county = models.ForeignKey(County, verbose_name=_('County'))
    municipality = models.ForeignKey(Municipality,
            verbose_name=_("Municipality"))

Существует две стороны проблемы: javaScript с клиентами и боковой рендером сервера.

Клиентский язык JavaScript (с jQuery, предполагается, что подается из /site_media/js/munisectality.js ): ):

var response_cache = {};

function fill_municipalities(county_id) {
  if (response_cache[county_id]) {
    $("#id_municipality").html(response_cache[county_id]);
  } else {
    $.getJSON("/municipalities_for_county/", {county_id: county_id},
      function(ret, textStatus) {
        var options = '<option value="" selected="selected">---------</option>';
        for (var i in ret) {
          options += '<option value="' + ret[i].id + '">'
            + ret[i].name + '</option>';
        }
        response_cache[county_id] = options;
        $("#id_municipality").html(options);
      });
  }
}

$(document).ready(function() {
  $("#id_county").change(function() { fill_municipalities($(this).val()); });
});

Теперь вам нужен вид AJAX для обслуживания муниципалитетов, которые принадлежат Данный округ (предполагается, что подается из / муниципальных средств_for_county / ):

from django.http import JSONResponse
from django.utils.encoding import smart_unicode
from django.utils import simplejson

from myproject.places.models import Municipality

def municipalities_for_county(request):
    if request.is_ajax() and request.GET and 'county_id' in request.GET:
        objs = Municipality.objects.filter(county=request.GET['county_id'])
        return JSONResponse([{'id': o.id, 'name': smart_unicode(o)}
            for o in objs])
    else:
        return JSONResponse({'error': 'Not Ajax or no GET'})

и, наконец, боковой код сервера в admin.py для рендеринга поля выглядит следующим образом. Во-первых, импорт:

from django import forms
from django.forms import widgets
from django.forms.util import flatatt
from django.utils.encoding import smart_unicode
from django.utils.safestring import mark_safe
from django.contrib import admin
from django.utils.translation import ugettext_lazy

from myproject.places.models import Municipality, Location

затем, виджет:

class MunicipalityChoiceWidget(widgets.Select):
    def render(self, name, value, attrs=None, choices=()):
        self.choices = [(u"", u"---------")]
        if value is None:
            # if no municipality has been previously selected,
            # render either an empty list or, if a county has
            # been selected, render its municipalities
            value = ''
            model_obj = self.form_instance.instance
            if model_obj and model_obj.county:
                for m in model_obj.county.municipality_set.all():
                    self.choices.append((m.id, smart_unicode(m)))
        else:
            # if a municipality X has been selected,
            # render only these municipalities, that belong
            # to X's county
            obj = Municipality.objects.get(id=value)
            for m in Municipality.objects.filter(county=obj.county):
                self.choices.append((m.id, smart_unicode(m)))

        # copy-paste from widgets.Select.render
        final_attrs = self.build_attrs(attrs, name=name)
        output = [u'<select%s>' % flatatt(final_attrs)]
        options = self.render_options(choices, [value])
        if options:
            output.append(options)
        output.append('</select>')
        return mark_safe(u'\n'.join(output))

Далее, форма:

class LocationForm(forms.ModelForm):
    municipality = forms.ModelChoiceField(Municipality.objects,
            widget=MunicipalityChoiceWidget(),
            label=ugettext_lazy("Municipality"), required=False)

    class Meta:
        model = Location

    def __init__(self, *args, **kwargs):
        """
        We need access to the county field in the municipality widget, so we
        have to associate the form instance with the widget.
        """
        super(LocationForm, self).__init__(*args, **kwargs)
        self.fields['municipality'].widget.form_instance = self

и, наконец, класс администратора:

class LocationAdmin(admin.ModelAdmin):
    form = LocationForm
    class Media:
        js = ('http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js',
                '/site_media/js/municipality.js')

admin.site.register(Location, LocationAdmin)

дайте мне знать, если что-то останется неясным.

24
ответ дан 4 December 2019 в 08:52
поделиться

Вы можете попытаться создать собственный виджет «адреса», который обрабатывает каскадирование с помощью трех раскрывающихся списков. Вы можете просмотреть исходный код виджета DateTime, чтобы узнать об этом.

Также ознакомьтесь с руководствами по созданию пользовательских виджетов, таких как этот .

0
ответ дан 4 December 2019 в 08:52
поделиться

It would be great if the dropdowns filter items based on the value of its parent.

You can use Ajax Form Machine of the dajaxproject for that part

0
ответ дан 4 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

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