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
-
- 407158
- 1
- Jul 5, 2015
Sin Respuesta
-
- 177
- 0
- Mar 19
-
- 93
- 2
- Feb 26
-
- 1176
- 0
- Nov 7, 2023
-
- 308
- 0
- Sep 19, 2023
-
- 310
- 0
- Ago 21, 2023
-
- 395
- 0
- May 14, 2023
-
- 363
- 0
- Abr 21, 2023
-
- 449
- 0
- Mar 31, 2023
- ver todas
Actividad Reciente
ArtEze respondió hace 3 días
Alguien sabe, no me ignorenArtEze seleccionó una respuesta hace 3 días
Bajar extensión de Chrome sin actualizar el navega…ArtEze respondió hace 3 días
Bajar extensión de Chrome sin actualizar el navega…ArtEze preguntó hace 3 días
Bajar extensión de Chrome sin actualizar el navega…ArtEze respondió hace 3 días
No me deja instalar OracleArtEze respondió hace 4 días
Formulario que guarde los datos de un jsonArtEze comentó hace 4 días
Script /boot/ scrapingSantiago2610 comentó Mar 23
Acualizar ChoiceField en djangoSantiago2610 preguntó Mar 19
Acualizar ChoiceField en djangogonzalss preguntó Feb 26
Script /boot/ scraping
Ultimas Preguntas
Usuarios Top
- Leonardo-Tadei
- 227320 Puntos
- Peter
- 150470 Puntos
- white
- 75880 Puntos
- carlossevi
- 63580 Puntos
- magarzon
- 30650 Puntos
- pregunton
- 20400 Puntos