Customized drop-downs using Django forms from a model
Django offers a lot of built-in functionality to kick off project activity day one, and provides flexibility for customization. The features of Django and object-oriented nature of Python, it is a very powerful web framework without a doubt.
Recently, I was working on a django formset, a pretty basic one, and added a foreign key item to the form with the idea of displaying a dropdown for the user to choose from. What I had initially was to list all the devices supported in System X. Great. I had a code snippet to accomplish this job using regular form/model elements. Great! I have a functional form in my UI.
But as the project requirements changed, I realized I need to customize this dropdown to show only a few items in the dropdown based on another field in the table. I needed something quick and dirty to get a solution to this problem, and there came customization of Django forms. I could override the ‘device_model’ field which is generating this dropdown for me in the ModelForm’s __init__ method.
Since I needed a solution more than an optimal solution to begin with, here is the __init__ method I came up with. You are intending to modify the form field and that is exactly what this code snippet achieves. In line 12, I add a default choices list, an empty one initialized. It should be noted that the device_model dropdown attribute is a django.forms.models.ModelChoiceIterator object. This object can be iterated upon but it cannot be indexed. Ok, so now that the context is established, I generate a list of cloud_devices which is the final list of selections I want from the currently existing dropdown choices. After this just iterate over the ‘device_model’ field queryset, and add whatever logic needs to be added, to get your required choices. Append a tuple to the initial choices list that was generated. The first item in the tuple is the device_model name and the second one is simply the entire object. So the last thing to be done is modify the existing ‘device_model’ field choices with the new one.
And this is what I get after using this customization:
This is exactly what I wanted – show all the devices which connect to the cloud to fetch information instead of showing a list of all devices. Quick! Isn’t it? [Of course a need to optimize this remains!]
Not only this, you could use this method to customize the way the object is listed in the dropdown or perform additional checks before a form is displayed.