views:

1428

answers:

5

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?

+1  A: 

Am thinking JavaScript/AJAX will be the best approach for this problem.

gath
+6  A: 

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.

Van Gale
+1 -> I was about to post something very similar. The OP just needs to populate the lists using the information in the db and then switch the options using the JS you provided :-)
Jon Cage
...or if you don't want to load it all at once, you could use some ajax to request the category from the server each time the user changes the option. Depends whether you want to take the hit up front or delay them when they're selecting...
Jon Cage
Thanks Jon. If you want to, you should go ahead an post your code that populates the lists at load time instead of ajax like mine. Then OP can choose the more appropriate.
Van Gale
I would if I had some to hand... AJAX is one aspect of Django I've yet to venture in to though. Soon though I'm sure :-)
Jon Cage
A: 

You will need to have some kind of non-server based mechanism of filtering the objects. Either that, or you can reload the page when the selection is made (which is likely to be done in JavaScript anyway).

Otherwise, there is no way to get the subset of data from the server to the client.

Matthew Schinckel
A: 

has anybody gotten this to work? since i am having troubles to get the js file to be executed. even though i suppose that i have set the MEDIA_URL appropiately. i have no experience with javascript whatsoever so that might leave me stuck as well since i try to adapt that script to my project.

MB_
A: 

I'm not having any luck with this javascript. It doesn't execute when I change the value of the first combo box. I'm trying to do this in a user-facing view, not in the admin, so I just included the javascript directly in the template for the appropriate view. Am I doing something wrong?

I actually use this in user facing views instead of admin. So a few things to check: Are you loading jquery? Are you sure the javascript isn't executing... because maybe it is but your Django view is configured wrong?
Van Gale