2009-04-28 53 views
10

tengo los siguientes modelos:Cómo limitar la elección de opciones de campo basado en otro campo de elección en administración de Django

class Category(models.Model): 
    name = models.CharField(max_length=40) 

class Item(models.Model): 
    name = models.CharField(max_length=40) 
    category = models.ForeignKey(Category) 

class Demo(models.Model): 
    name = models.CharField(max_length=40) 
    category = models.ForeignKey(Category) 
    item = models.ForeignKey(Item) 

En la interfaz de administración cuando se crea una nueva demostración, cuando el usuario coge la categoría en el menú desplegable, lo haría desea limitar el número de opciones en el menú desplegable "Elementos". Si el usuario selecciona otra categoría, las opciones de elementos deberían actualizarse en consecuencia. Me gustaría limitar las opciones de artículos directamente en el cliente, incluso antes de que llegue a la validación del formulario en el servidor. Esto es para la usabilidad, ya que la lista de elementos podría ser más de 1000 y poder reducirla por categoría ayudaría a que sea más manejable.

¿Hay una "manera django" de hacerlo o JavaScript personalizado es la única opción aquí?

+1

¿Realmente no hay forma de configurar esto en los modelos Django? –

+0

Sí, lo hay. Con una aplicación de terceros. Ver mi respuesta –

Respuesta

10

Aquí es un poco de Javascript (basado jQuery) para cambiar los valores de la opción del artículo cuando los cambios de categoría:

<script charset="utf-8" type="text/javascript"> 
    $(function(){ 
    $("select#id_category").change(function(){ 
     $.getJSON("/items/",{id: $(this).val(), view: 'json'}, function(j) { 
     var options = '<option value="">--------&nbsp;</option>'; 
     for (var i = 0; i < j.length; i++) { 
      options += '<option value="' + j[i].optionValue + '">' + j[i].optionDisplay + '</option>'; 
     } 
     $("#id_item").html(options); 
     $("#id_item option:first").attr('selected', 'selected'); 
     }) 
     $("#id_category").attr('selected', 'selected'); 
    }) 
    }) 
</script> 

Se necesita un punto de vista que se ha pedido a las/los artículos/URL que proporciona una lista de JSON del válida artículos.

Puede conectar esto a su administrador utilizando model admin media definitions.

+0

+1 -> Estaba a punto de publicar algo muy similar. El OP solo necesita llenar las listas usando la información en el archivo db y luego cambiar las opciones usando el JS que proporcionó :-) –

+0

... o si no quiere cargarlo todo de una vez, puede usar un poco de ajax para solicitar la categoría del servidor cada vez que el usuario cambie la opción. Depende de si desea tomar el golpe por adelantado o retrasarlos cuando están seleccionando ... –

+0

Gracias Jon. Si quieres, debes seguir publicando tu código que rellena las listas en el momento de la carga en lugar de ajax como el mío. Entonces OP puede elegir el más apropiado. –

0

Estoy pensando que JavaScript/AJAX será el mejor enfoque para este problema.

+3

Parece más un comentario sobre la respuesta anterior que su propia respuesta. – boatcoder

0

Necesitará tener algún tipo de mecanismo no basado en el servidor para filtrar los objetos. O eso, o puede volver a cargar la página cuando se realiza la selección (lo que es probable que se haga en JavaScript de todos modos).

De lo contrario, no hay forma de obtener el subconjunto de datos del servidor al cliente.

4

Hay django-smart-selects:

Si tiene el siguiente modelo:

class Location(models.Model) 
    continent = models.ForeignKey(Continent) 
    country = models.ForeignKey(Country) 
    area = models.ForeignKey(Area) 
    city = models.CharField(max_length=50) 
    street = models.CharField(max_length=100) 

Y quieres que si selecciona un continente sólo los países están disponibles que se encuentran en este continente y lo mismo para áreas que puede hacer lo siguiente:

from smart_selects.db_fields import ChainedForeignKey 

class Location(models.Model) 
    continent = models.ForeignKey(Continent) 
    country = ChainedForeignKey(
     Country, 
     chained_field="continent", 
     chained_model_field="continent", 
     show_all=False, 
     auto_choose=True 
    ) 
    area = ChainedForeignKey(Area, chained_field="country", chained_model_field="country") 
    city = models.CharField(max_length=50) 
    street = models.CharField(max_length=100) 
Cuestiones relacionadas