Django chained selects with mootools
You can also be interested in:
Notice!
A due specification here!
Such method works, but IMHO should not be used with a large amount of data, since it uses a js mapping array, but is simple and requires a few lines of code, so why not to use it when we have a controlled set of data?
Introduction
This is just yet another method to implement chained (cascading) selects in django forms. I'm focusing here on the frontend form construction, not the admin area. If you're interested in the admin area instead, please take a look here.
Scenario
Imagine we have such models:
class City(models.Model):
name = models.CharField('name')
class Installation(models.Model):
name = models.CharField('name')
city = models.ForeignKey(City)
and imagine we need to create a form where the user can select a city or an installation, but if he selects a city then only the associated installations are available. We can solve the problem as described in the next section.
Implemetation
In the view we create a dictionary which maps the city/installation association:
def myview(request):
all_installation = Installation.objects.all()
installation_city_map = {}
for i in all_installation:
installation_city_map[int(i.id)] = int(i.commune.id)
# construct and process the form object...
return render_to_response('view.html', {'form': form, 'installation_city_map':
installation_city_map}, context_instance=RequestContext(request))
Ok, in the template we have to add a javascript which creates an array from the installation_city_map dictionary, as follows:
<script>
var map = [];
{% for m in installation_city_map %}
map[{{ m }}] = {{ installation_city_map|get_item:m }};
{% endfor %}
</script>
<!-- Here comes the form -->
Here we need 2 things:
- mootools loaded in the page
-
the custom template filter get_item. Its implementation it's quite simple:
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
Finally we have to use our javascript map array when the onchange event of the city select field is fired, so in the form.py:
class MyForm(forms.Form):
onchange = "(function() { $$('#id_installation option').each(function(opt) { if($(this).value && opt.value && map[opt.value] != $(this).value) opt.setStyle('display', 'none'); else opt.setStyle('display', 'block'); }.bind(this)) }.bind(this))()"
city = forms.ModelChoiceField(label='city', queryset=City.objects.all(), required=False, widget=forms.Select(attrs={'onchange':onchange}))
installation = forms.ModelChoiceField(label='installation', queryset=Installation.objects.all(), required=False)
That's it, no further implementation is required, please comment here for suggestions.
Your Smartwatch Loves Tasker!
Your Smartwatch Loves Tasker!
Featured
Archive
- 2021
- 2020
- 2019
- 2018
- 2017
- Nov
- Oct
- Aug
- Jun
- Mar
- Feb
- 2016
- Oct
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2015
- Nov
- Oct
- Aug
- Apr
- Mar
- Feb
- Jan
- 2014
- Sep
- Jul
- May
- Apr
- Mar
- Feb
- Jan
- 2013
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2012
- Dec
- Nov
- Oct
- Aug
- Jul
- Jun
- May
- Apr
- Jan
- 2011
- Dec
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May