2009-04-28 11 views
10

mam następujące modele:Jak ograniczyć opcje pól wyboru na podstawie innego pola wyboru w Django administratora

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) 

w interfejsie administratora podczas tworzenia nowego Demo, po użytkownik wybiera kategorię z menu, chciałbym jak ograniczyć liczbę opcji w menu "Elementy". Jeśli użytkownik wybierze inną kategorię, wybór elementów powinien zostać odpowiednio zaktualizowany. Chciałbym ograniczyć wybór elementów bezpośrednio na kliencie, zanim jeszcze trafi on na walidację formularzy na serwerze. Jest to przydatne ze względu na użyteczność, ponieważ lista pozycji może mieć wartość 1000+, co oznacza, że ​​można ją zawęzić według kategorii, co ułatwiłoby zarządzanie.

Czy istnieje "django-way" tego działania lub czy niestandardowy JavaScript jest jedyną opcją tutaj?

+1

Czy naprawdę nie ma sposobu, aby ustawić to w modelach Django? –

+0

Tak, jest. Za pomocą aplikacji innej firmy. Zobacz moją odpowiedź. –

Odpowiedz

10

Oto niektóre javascript (jQuery oparte), aby zmienić wartości Element Opcja podczas zmian kategorii:

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

Trzeba aby być w nazwie na/przedmiotów/URL, który dostarcza listę JSON ważnego przedmiotów.

Możesz to podłączyć do administratora za pomocą model admin media definitions.

+0

+1 -> Już miałem opublikować coś bardzo podobnego. OP musi wypełnić listy używając informacji w db, a następnie przełącz opcje używając JS, który podałeś :-) –

+0

... lub jeśli nie chcesz załadować go od razu, możesz użyć jakiegoś ajaxa aby zażądać kategorii od serwera za każdym razem, gdy użytkownik zmieni opcję. Zależy od tego, czy chcesz wykonać uderzenie z góry, czy opóźnić je, gdy wybierają ... –

+0

Dzięki Jon. Jeśli chcesz, powinieneś napisać swój kod, który zapełnia listy w czasie ładowania, a nie jak mój ajax. Wtedy OP może wybrać bardziej odpowiedni. –

0

Myślenie JavaScript/AJAX będzie najlepszym podejściem do tego problemu.

+3

Wygląda bardziej na komentarz do powyższej odpowiedzi niż na własną odpowiedź. – boatcoder

0

Potrzebny będzie jakiś mechanizm filtrowania obiektów oparty na niezwiązanych z serwerem. Albo to, albo możesz ponownie załadować stronę po dokonaniu wyboru (co i tak prawdopodobnie zostanie zrobione w JavaScript).

W przeciwnym razie nie ma sposobu na pobranie podzbioru danych z serwera do klienta.

4

Jest django-smart-selects:

Jeśli masz następujący model:

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) 

I chcesz, że jeśli zostanie wybrany kontynent tylko kraje są dostępne, które znajdują się na tym kontynencie i tym samym do obszary można wykonać następujące:

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) 
Powiązane problemy