Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit choice field options based on another choice field in django admin

I have the following models:

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)

In the admin interface when creating a new Demo, after user picks category from the dropdown, I would like to limit the number of choices in the "items" drop-down. If user selects another category then the item choices should update accordingly. I would like to limit item choices right on the client, before it even hits the form validation on the server. This is for usability, because the list of items could be 1000+ being able to narrow it down by category would help to make it more manageable.

Is there a "django-way" of doing it or is custom JavaScript the only option here?

like image 716
Sergey Golovchenko Avatar asked Apr 28 '09 06:04

Sergey Golovchenko


People also ask

How do I use multiple choice fields in Django?

MultipleChoiceField in Django Forms is a Choice field, for input of multiple pairs of values from a field. The default widget for this input is SelectMultiple. It normalizes to a Python list of strings which you one can use for multiple purposes.

How do I make a field optional in Django?

You would have to add blank=True as well in field definition. If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True. Don't forget to reset and sync DB again after changing this.

How do you make a field non editable in Django admin?

editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form. The field will not be displayed in the admin or any other ModelForm.

How do you make a field non mandatory in Django?

The simplest way is by using the field option blank=True (docs.djangoproject.com/en/dev/ref/models/fields/#blank).


1 Answers

Here is some javascript (JQuery based) to change the item option values when category changes:

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

You need a view to be called on the /items/ URL that supplies a JSON list of the valid items.

You can hook this into your admin by using model admin media definitions.

like image 107
Van Gale Avatar answered Oct 15 '22 18:10

Van Gale