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]));
}
}
});
});
});
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);
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.