Select dependent on Django?

4

How do I place four select to my template that show state, municipality, location? and of course, if the user selects the state DF, the other select only brings the municipalities and localities. How do I do it?

In order to save them already stored in combox, to a table of users who register and select their state, municipality and location, thanks.

    
asked by joselitoo 04.01.2016 в 18:07
source

2 answers

5

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>
    
answered by 04.01.2016 в 21:40
3

Do not complicate your life, this package will help you - link

Your models only need a very light adjustment to chain them, the package is self-explanatory.

    
answered by 24.01.2016 в 22:24