What you have to do is create the form with your three tables, then using AJAX and jQuery to dynamically consult the models according to the option that the user has selected.
First, the form. Note that in the queryset
of each ModelChoiceField
I'm using a all()
, this is necessary so that you can choose a valid option when using AJAX to filter the results.
forms.py:
from django import forms
from .models import Estado, Municipio, Localidad
class UbicacionForm(forms.Form):
estado = forms.ModelChoiceField(
label=u'Estado',
queryset=Estado.objects.all()
)
municipio = forms.ModelChoiceField(
label=u'Municipio',
queryset=Municipio.objects.all()
)
localidad = forms.ModelChoiceField(
label=u'Localidad',
queryset=Localidad.objects.all()
)
def __init__(self, *args, **kwargs):
super(UbicacionForm, self).__init__(*args, **kwargs)
self.fields['municipio'].queryset = Municipio.objects.none()
self.fields['localidad'].queryset = Localidad.objects.none()
In the view, you would have something like this.
views.py:
from django.core.urlresolvers import reverse
from djabgo.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UbicacionForm
from .models import Municipio, Localidad
def vista_ubicacion(request):
form = UbicacionForm()
if request.method == 'POST':
form = UbicacionForm(request.POST)
if form.is_valid():
# Guardar los datos
url = reverse('home')
return HttpResponseRedirect(url)
return render(request, 'template.html', {
'form': form
})
We create the functions that will receive the filters via AJAX, these functions are what should be called from your template.
ajax.py:
from django.http import JsonResponse
from .models import Localidad, Municipio
def get_municipios(request):
estado_id = request.GET.get('estado_id')
municipios = Municipio.objects.none()
options = '<option value="" selected="selected">---------</option>'
if estado_id:
municipios = Municipio.objects.filter(estado_id=estado_id)
for municipio in municipios:
options += '<option value="%s">%s</option>' % (
municipio.pk,
municipio.municipio
)
response = {}
response['municipios'] = options
return JsonResponse(response)
def get_localidades(request):
municipio_id = request.GET.get('municipio_id')
localidades = Localidad.objects.none()
options = '<option value="" selected="selected">---------</option>'
if municipio_id:
localidades = Localidad.objects.filter(municipio_id=municipio_id)
for localidad in localidades:
options += '<option value="%s">%s</option>' % (
localidad.pk,
localidad.localidad
)
response = {}
response['localidades'] = options
return JsonResponse(response)
Since we have added new functions, we need to create the path to those AJAX functions by updating the URLs.
urls.py:
from django.conf.urls import url
from .ajax import get_municipios, get_localidades
urlpatterns = [
url(r'^ajax/get_municipios/$', get_municipios, name='get_municipios'),
url(r'^ajax/get_localidades/$', get_localidades, name='get_localidades'),
# ...
]
Now, we need that when a state is selected, the municipalities are filtered, and that when a municipality is selected, the localities are filtered. We have to define this in the template (or in a JavaScript file imported into your template) using a <script></script>
.
template.html:
<body>
<form method="POST">
{% csrf_token %}
<div>
{{ form.estado.label_tag }}
{{ form.estado }}
</div>
<div>
{{ form.municipio.label_tag }}
{{ form.municipio }}
</div>
<div>
{{ form.localidad.label_tag }}
{{ form.localidad }}
</div>
<button type="submit">Guardar</button>
</form>
<script type="text/javascript">
$(document).ready(function() {
$("#id_estado").on("change", getMunicipios);
$("#id_estado").on("change", getLocalidades);
});
function getMunicipios() {
var estadoId = $("#id_estado").val();
if (estadoId) {
// Eliminamos las opciones anteriores del select
$("#id_municipio").html("");
var request = $.ajax({
type: "GET",
url: "{% url 'get_municipios' %}",
data: {
"estado_id": estadoId,
},
});
request.done(function(response) {
// Agregamos los resultados al select
$("#id_proceso").html(response.municipios);
$("#id_localidad").html("<option value='' selected='selected'>---------</option>");
$("#id_municipio, #id_localidad").trigger("change");
});
} else {
$("#id_municipio").html("<option value='' selected='selected'>---------</option>");
$("#id_localidad").html("<option value='' selected='selected'>---------</option>");
$("#id_municipio, #id_localidad").trigger("change");
}
}
function getLocalidades() {
var municipioId = $("#id_municipio").val();
if (municipioId) {
// Eliminamos las opciones anteriores del select
$("#id_localidad").html("");
var request = $.ajax({
type: "GET",
url: "{% url 'get_localidades' %}",
data: {
"municipio_id": municipioId,
},
});
request.done(function(response) {
// Agregamos los resultados al select
$("#id_localidad").html(response.localidades);
$("#id_localidad").trigger("change");
});
} else {
$("#id_localidad").html("<option value='' selected='selected'>---------</option>");
$("#id_localidad").trigger("change");
}
}
</script>
</body>