Cómo hago para colocar cuatro select a mi template que muestren estado, municipio, parroquia y ciudad? y por supuesto, si el usuario selecciona el estado Aragua, el otro select traiga solamente los municipios, parroquias y ciudades de Aragua. Cómo lo hago?
entre Desarrolladores
Recibe ayuda de expertos
Registrate y pregunta
Es gratis y fácil
Recibe respuestas
Respuestas, votos y comentarios
Vota y selecciona respuestas
Recibe puntos, vota y da la solución
Pregunta
2 Respuestas
Eso se hace utilizando ajax, para que haga la petición al servidor y devuelva los datos sin recargar la página.
Por favor, accede o regístrate para añadir un comentario.
Tomando en cuenta tu pregunta anterior:
¿Crear cuadro de búsqueda con Ajax en Django?
Saltaré ciertas cosas,
Necesitas una app o una vista que controle la petición ajax.
views.py
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound
from <TuApp>.models import Ciudades, Estados, Municipios, Parroquias
import json
def geo(request, type = None, parent_id = None):
if not request.is_ajax():
return HttpResponseBadRequest('<h1>%s</h1>' % 'bad request')
# para testear el efecto loading
#time.sleep(1);
locations = {
###################################################################
# Localidad => [modelo, modelo padre, foreignkey, parent type] #
###################################################################
'estados' : [Estados],
'ciudades' : [Ciudades, Estados, 'estado_id', 'estado'],
'municipios' : [Municipios, Estados, 'estado_id', 'estado'],
'parroquias' : [Parroquias, Municipios, 'municipio_id', 'municipio']
}
location_exists = False
if parent_id != None:
location_exists = (locations[type][2].objects.filter(id = parent_id).count() > 0)
else:
location_exists = (locations[type][0].objects.count() > 0)
if not location_exists:
return HttpResponseBadRequest('Identificador inválido')
data_fields = {
'estados' : ('id', 'estado'),
'ciudades' : ('id', 'ciudad'),
'municipios' : ('id', 'municipio'),
'parroquias' : ('id', 'parroquia')
}
extra_where = None
if parent_id != None:
extra_where = ['%s = %d' % (locations[type][2], int(parent_id))]
location_result = locations[type][0].objects.extra(where = extra_where).values(*data_fields[type]).order_by('id')
if not location_result.count() > 0:
return HttpResponseNotFound(json.dumps({'error' : 'empty'}))
data = {
'parent' : None,
'data' : list(location_result)
}
if parent_id != None:
data['parent'] = {
'id' : parent_id,
'type' : locations[type][3]
}
output = json.dumps(data)
return HttpResponse(output, content_type = 'application/json')
reemplaza <TuApp>
de: from <TuApp>.models import Ciudades, Estados, Municipios, Parroquias
por el nombre de tu aplicación.
En el url dispatcher necesitas 2 reglas:
urls.py
url(r'^geo/(?P<type>estados)/$', home.views.geo, name='geo'),
url(r'^geo/(?P<type>ciudades|municipios|parroquias)/(?P<parent_id>[0-9]+)$', home.views.geo, name='geo'),
la expresion regular ^geo/(?P<type>ciudades|municipios|parroquias)/(?P<parent_id>[0-9]+)$
toma el tipo de localidad y el identificador de la localidad padre
ejemplo: /geo/ciudades/1, donde "1" es el identificador de un Estado.
Para los modelos hay 4 clases:
class Estados(models.Model):
class Ciudades(models.Model):
class Municipios(models.Model):
class Parroquias(models.Model):
models.py
class Estados(models.Model):
id = models.AutoField(primary_key = True)
estado = models.TextField(max_length = 255)
iso_3166_2 = models.TextField(max_length = 4)
def __str__(self):
return '{0}'.format(self.estado)
class Ciudades(models.Model):
id = models.AutoField(primary_key = True)
estado = models.ForeignKey(Estados)
ciudad = models.TextField(max_length = 255)
capital = models.SmallIntegerField()
def __str__(self):
return '{0}'.format(self.ciudad)
class Municipios(models.Model):
id = models.AutoField(primary_key = True)
estado = models.ForeignKey(Estados)
municipio = models.TextField(max_length = 100)
def __str__(self):
return '{0}'.format(self.municipio)
class Parroquias(models.Model):
id = models.AutoField(primary_key = True)
municipio = models.ForeignKey(Municipios)
parroquia = models.TextField(max_length = 255)
def __str__(self):
return '{0}'.format(self.parroquia)
El codigo javascript controla los dropdown y la peticion ajax:
script.js
function set_multiselect()
{
var multiselect = $('.multiselect');
$(multiselect).find('select').each(function(){
$(this).append(
$('<option>')
.val('0')
.text($(this).attr('title'))
.addClass('label')
)
.addClass('disabled')
.prop('disabled', true)
});
get_geo(
$(multiselect).find('select').first(),
[$(multiselect).find('select').first().attr('data-query')]
);
$(multiselect).find('select').each(function(){
$(this).on('change', function(){
if(!$(this).val() || !$(this).next().is('select'))
return false;
var parent_val = false,
query_val;
if(typeof $(this).attr('data-parent') !== 'undefined')
parent_val = $(multiselect).find('select[name=' + $(this).next().attr('data-parent') + ']').val();
query_val = parent_val || $(this).val();
if(parseInt(query_val) === 0)
return false;
if($(this).children().length > 1)
{
var current = $(this);
do
{
current = $(current).next();
$(current).find('option:not(.label)').remove();
}
while(!$(current).is(':last-child'));
}
get_geo($(this).next(), [
$(this).next().attr('data-query'),
query_val
]);
});
});
}
var geo_cache = [];
function get_geo(dropdown, query)
{
var fill_dropdown = function(data){
for(var x in data)
{
$(dropdown).append(
$('<option>')
.val(data[x].id)
.text(data[x][$(dropdown).attr('name')])
)
}
$(dropdown).prop('disabled', false).removeClass('disabled');
};
if(!geo_cache[query.join('.')])
geo_cache[query.join('.')] = [];
else
return fill_dropdown(geo_cache[query.join('.')]);
$(dropdown).addClass('loading');
$.ajax({
dataType : 'json',
type : 'GET',
url : '/geo/' + query.join('/'),
success : function(h) {
fill_dropdown(h.data);
geo_cache[query.join('.')] = h.data;
},
error : function(h) {
if(h.error == 'empty')
{
$(dropdown).find('option:not(.label)').remove();
}
},
complete : function()
{
$(dropdown).removeClass('loading');
}
});
}
$(document).ready(set_multiselect);
requisitos: Jquery
La estructura de los dropdown debe ser esta para funcionar:
<div class="multiselect">
<select name="estado" data-query="estados" title="Estado"></select>
<select name="ciudad" data-query="ciudades" data-parent="estado" title="Ciudad"></select>
<select name="municipio" data-query="municipios" data-parent="estado" title="Municipio"></select>
<select name="parroquia" data-query="parroquias" data-parent="municipio" title="Parroquia"></select>
</div>
data-query: tiene el primer parametro para la peticion ajax (ejemplo: /geo/ciudades/).
data-parent: tiene el nombre de la localidad padre.
Necesitarias hacer las consultas respectivas, con la base de datos de las localidades
Lista de ciudades de Venezuela para un select en Django
Te adjunto un dump de sqlite.
Demo online: https://warm-tor-8879.herokuapp.com/
Dump sqlite: https://db.tt/enBUJ70K
Por favor, accede o regístrate para añadir un comentario.
Por favor, accede o regístrate para responder a esta pregunta.
En el blog
-
- 676856
- 1
- Jul 5, 2015
Sin Respuesta
-
- 63
- 0
- Oct 18
-
- 153
- 0
- Jul 9
-
- 514
- 1
- Mar 19
-
- 383
- 2
- Feb 26
-
- 4569
- 0
- Nov 7, 2023
-
- 473
- 0
- Sep 19, 2023
-
- 451
- 0
- Ago 21, 2023
-
- 632
- 0
- May 14, 2023
- ver todas
Actividad Reciente
alyvrs preguntó Oct 19
Ayuda , necesito mostrar datos creados solo por el…ManHol preguntó Jul 9
pasar un archivo de excel a csv en pythonArtEze respondió Abr 24
Alguien sabe, no me ignorenArtEze seleccionó una respuesta Abr 24
Bajar extensión de Chrome sin actualizar el navega…ArtEze respondió Abr 24
Bajar extensión de Chrome sin actualizar el navega…ArtEze preguntó Abr 24
Bajar extensión de Chrome sin actualizar el navega…ArtEze respondió Abr 24
No me deja instalar OracleArtEze respondió Abr 24
Formulario que guarde los datos de un jsonArtEze comentó Abr 24
Script /boot/ scrapingSantiago2610 comentó Mar 23
Acualizar ChoiceField en django
Ultimas Preguntas
Usuarios Top
- Leonardo-Tadei
- 227320 Puntos
- Peter
- 150480 Puntos
- white
- 75880 Puntos
- carlossevi
- 63580 Puntos
- magarzon
- 30650 Puntos
- pregunton
- 20400 Puntos