2009-04-28 12 views
10

Ho i seguenti modelli:Come limitare le opzioni di campo di scelta in base a un altro campo scelta Django Admin

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) 

nella interfaccia di amministrazione quando si crea un nuovo demo, dopo che l'utente prende categoria dal menu a discesa, lo farei come limitare il numero di scelte nel menu a discesa "items". Se l'utente seleziona un'altra categoria, le scelte degli elementi dovrebbero essere aggiornate di conseguenza. Vorrei limitare le scelte degli articoli direttamente sul client, prima che colpisca anche la convalida del modulo sul server. Questo è per l'usabilità, perché l'elenco degli articoli potrebbe essere 1000+, essendo in grado di restringerlo per categoria, contribuirebbe a renderlo più gestibile.

C'è un "modo django" di farlo o il JavaScript personalizzato è l'unica opzione qui?

+1

Non c'è davvero alcun modo per impostare questo nei modelli Django? –

+0

Sì, c'è. Con un'app di terze parti. Vedi la mia risposta. –

risposta

10

Ecco alcuni javascript (basata JQuery) per modificare i valori di opzione articolo quando cambi di categoria:

<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> 

È necessario, al fine di essere invitato i/oggetti/URL che fornisce un elenco JSON della valida elementi.

È possibile collegarlo all'amministratore utilizzando model admin media definitions.

+0

+1 -> Stavo per pubblicare qualcosa di molto simile. L'OP deve solo compilare gli elenchi usando le informazioni nel db e quindi cambiare le opzioni usando il JS che hai fornito :-) –

+0

... o se non vuoi caricarlo tutto in una volta, potresti usare un po 'di ajax per richiedere la categoria dal server ogni volta che l'utente cambia l'opzione. Dipende se vuoi prendere il colpo in attacco o ritardarlo quando lo stanno selezionando ... –

+0

Grazie Jon. Se vuoi, devi andare avanti e pubblicare il tuo codice che compila gli elenchi al momento del caricamento invece che ajax come il mio. Quindi OP può scegliere il più appropriato. –

0

Penso che JavaScript/AJAX sia l'approccio migliore per questo problema.

+3

Sembra più un commento sulla risposta sopra che la propria risposta. – boatcoder

0

È necessario disporre di una sorta di meccanismo non basato sul server per filtrare gli oggetti. Oppure, oppure puoi ricaricare la pagina quando viene effettuata la selezione (che è probabile venga comunque eseguita in JavaScript).

In caso contrario, non è possibile ottenere il sottoinsieme di dati dal server al client.

4

C'è django-smart-selects:

Se avete il seguente modello:

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) 

E vuoi che se si seleziona un continente solo i paesi sono disponibili che si trovano in questo continente e lo stesso per aree che puoi fare come segue:

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) 
Problemi correlati