5

I have a model in django admin as follows

ChoiceA= (
      ("on-false","on-false"),
       ("on-true","on-true"),
     )

ChoiceB =  (
        ("always","always"),
        ("never","never"),
       )
   id = models.CharField(verbose_name="Field",max_length=32)
   type = models.CharField(verbose_name="Expression",max_length=32)
   action = models.CharField(max_length=32, choices=x)

Now based on the type entered by the user ie if user enters type = "a" then action's choices should be set to ChoiceA and if user enters type ="b" then action's choices should be set to ChoiceB. How can I achieve this in Django Admin?

Edit:

action_change.js

jQuery(document).ready(function(){
$("#id_type").change( function(event) {
$.ajax({
        "type"     : "POST",
        "url"      : "/action_choices/",
        "dataType" : "json",
        "cache"    : false,
        "error"   :  alert("hello"),  
        "success"  : function(json) {
            $('#id_action >option').remove();
            for(var j = 0; j < json.length; j++){
                $('#id_action').append($('<option></option>').val(json[j][0]).html(json[j][1]));
            }
        }

});
});
});
arulmr
  • 8,620
  • 9
  • 54
  • 69
arjun
  • 2,333
  • 4
  • 21
  • 21

2 Answers2

7

You can achieve it using Ajax and jQuery:

models.py:

type   = models.CharField(verbose_name="Expression",max_length=32)
action = models.CharField(max_length=32, choices = (('', ''), ))

admin.py:

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('type', )

    class Media:
        js = ['/static/js/action_change.js']

admin.site.register(MyModel, MyModelAdmin)

urls.py:

url(r'^action_choices/', 'myproject.myapp.views.action_choices'),

views.py:

def action_choices(request): 
    action_list = []
    ChoiceA = ("on-false", "on-true")
    ChoiceB = ("always", "never")

    action_type = request.GET.get('action_type')
    if str(action_type).lower() == 'a':
        choices = ChoiceA
    elif str(action_type).lower() == 'b':
        choices = ChoiceB
    else:
        choices = ()

    [action_list.append((each,each)) for each in choices]
    json = simplejson.dumps(action_list)
    return HttpResponse(json, mimetype='application/javascript')

Create the file action_change.js with following content in your static folder and define correct path in class Media of ModelAdmin.

action_change.js

(function($){   
    $(function(){
        $(document).ready(function() {
            $('#id_type').bind('keyup', type_change);           
            $('#id_action >option').show();
        });
});  
})(django.jQuery);

// based on the type, action will be loaded

var $ = django.jQuery.noConflict();

function type_change()
{
    var action_type = $('#id_type').val();
    $.ajax({
            "type"     : "GET",
            "url"      : "/action_choices/?action_type="+action_type,
            "dataType" : "json",
            "cache"    : false,
            "success"  : function(json) {
                $('#id_action >option').remove();
                for(var j = 0; j < json.length; j++){
                    $('#id_action').append($('<option></option>').val(json[j][0]).html(json[j][1]));
                }
            }           
    })(jQuery);
}

This should work fine for the scenario you asked. And I'm giving my suggestion below:

models.py

type   = models.CharField(verbose_name="Expression",max_length=32, choices = (('a', 'a'), ('b', 'b'), ))
action = models.CharField(max_length=32, choices = (('', ''), ))

action_change.js (line 5)

$('#id_type').bind('change', type_change);
arulmr
  • 8,620
  • 9
  • 54
  • 69
  • Actually when I tried as you said the action field did not load. So I changed the action_change.js file as follows. But now it gives Property 'jQuery' of object [object Window] is not a function – arjun Feb 26 '13 at 08:33
  • The action field will be loaded only when there is a value in type field. – arulmr Feb 26 '13 at 08:40
  • Could you pls edit the above code I pasted with the right solution – arjun Feb 26 '13 at 08:42
  • What was the issue you faced with my code? If you can explain clearly, I can help you better. – arulmr Feb 26 '13 at 08:48
  • When i select a type the corresponding action is not loaded. The action field remains blank with a blank choice in it. There are no errors displayed. – arjun Feb 26 '13 at 09:20
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/25132/discussion-between-arulmr-and-arjun) – arulmr Feb 26 '13 at 09:24
1

You would have to initialize the action field with all possible choices, or Django will complain that a choice that didn't previously exist isn't a valid choice.

My recommendation would be to initialize the field with all of the possible choices, and use JavaScript to toggle the visibility of the choices, depending on the value of type. There are a few plugins around that will handle dynamic fields in Django admin, but most that I've seen deal with ForeignKey or ManyToMany fields that need to do lookups.

You're probably best off just adding some JavaScript to your admin form via the Media meta class and handling it yourself.

Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144