2009-04-28 8 views
10

Je les modèles suivants:Comment limiter les options sur le terrain de choix basé sur un autre champ de choix dans 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) 

Dans l'interface d'administration lors de la création d'une nouvelle démonstration, après que l'utilisateur reprend la catégorie dans le menu déroulant, je le ferais aime limiter le nombre de choix dans la liste déroulante "articles". Si l'utilisateur sélectionne une autre catégorie, les choix d'éléments doivent être mis à jour en conséquence. Je voudrais limiter les choix d'éléments directement sur le client, avant même qu'il ne frappe la validation de formulaire sur le serveur. C'est pour la facilité d'utilisation, parce que la liste des éléments pourrait être 1000+ être en mesure de le réduire par catégorie aiderait à le rendre plus gérable.

Existe-t-il un "django-way" ou le JavaScript personnalisé est-il la seule option ici?

+1

Est-il vraiment impossible de régler ceci dans les modèles Django? –

+0

Ouais il y a. Avec une application tierce Vois ma réponse. –

Répondre

10

Voici javascript (JQuery base) pour modifier les valeurs des options de poste lorsque des modifications de catégorie:

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

Vous devez en vue d'appeler les/articles/URL qui fournit une liste de JSON de la validité articles.

Vous pouvez accrocher ceci dans votre admin en utilisant model admin media definitions.

+0

+1 -> J'étais sur le point de poster quelque chose de très similaire. L'OP a juste besoin de remplir les listes en utilisant les informations de la base de données puis de changer les options en utilisant le JS que vous avez fourni :-) –

+0

... ou si vous ne voulez pas le charger tout d'un coup, vous pouvez utiliser un ajax pour demander la catégorie du serveur chaque fois que l'utilisateur change l'option. Cela dépend si vous voulez prendre le coup avant ou les retarder quand ils sélectionnent ... –

+0

Merci Jon. Si vous voulez, vous devriez aller de l'avant un code postal qui remplit les listes au moment du chargement au lieu d'ajax comme le mien. Ensuite, OP peut choisir le plus approprié. –

0

Je pense que JavaScript/AJAX sera la meilleure approche pour ce problème.

+3

Cela ressemble plus à un commentaire sur la réponse ci-dessus qu'à sa propre réponse. – boatcoder

0

Vous aurez besoin d'une sorte de mécanisme de filtrage des objets non basé sur le serveur. Soit cela, ou vous pouvez recharger la page lorsque la sélection est faite (ce qui est susceptible d'être fait en JavaScript de toute façon).

Sinon, il n'existe aucun moyen d'obtenir le sous-ensemble de données du serveur au client.

4

Il est django-smart-selects:

Si vous avez le modèle suivant:

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) 

Et vous voulez que si vous sélectionnez un continent que les pays sont disponibles qui se trouvent sur ce continent et même pour les zones que vous pouvez faire ce qui suit:

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) 
Questions connexes