Saltar al contenido

Menús desplegables de país/estado/ciudad dentro del administrador de Django en línea

Deseamos darte la mejor solución que encontramos en todo internet. Nosotros queremos que te sea de mucha ayuda y si puedes compartir alguna mejora siéntete libre de hacerlo..

Solución:

Con un poco de hackery, es bastante factible.

En el siguiente ejemplo, condado se utiliza en lugar de Estado y Municipio en lugar de Ciudad. Entonces, los modelos son los siguientes:

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

Hay dos lados del problema: JavaScript del lado del cliente y representación de campo del lado del servidor.

El JavaScript del lado del cliente (con JQuery, se supone que se sirve desde /site_media/js/municipalidad.js) es como sigue:

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 = '';
        for (var i in ret) 
          options += '';
        
        response_cache[county_id] = options;
        $("#id_municipality").html(options);
      );
  


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

Ahora necesita la vista Ajax para servir a los municipios que pertenecen a un condado determinado (se supone que se sirve desde /municipalities_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')

Y finalmente el código del lado del servidor en administrador.py para representar el campo es el siguiente. Primero, las importaciones:

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

Entonces, el widget:

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'' % flatatt(final_attrs)]
        options = self.render_options(choices, [value])
        if options:
            output.append(options)
        output.append('')
        return mark_safe(u'n'.join(output))

A continuación, el formulario:

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

Y finalmente, la clase de administrador:

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)

Avísame si algo no está claro.

Al final de todo puedes encontrar las ilustraciones de otros administradores, tú además puedes dejar el tuyo si te apetece.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *