- Author:
- anentropic
- Posted:
- November 10, 2009
- Language:
- Python
- Version:
- 1.1
- Score:
- 1 (after 1 ratings)
Say you have a ModelChoiceField and you want the choices to depend on the value of another field in the form... that's what these bits are for.
They need to be used in conjunction with the Ajax views from: code.google.com/p/django-ajax-filtered-fields/
See my blog for full details: anentropic.wordpress.com
...um, this is work in progress and the explanatory blog post is not up yet...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | class AjaxAutoSelect(forms.Select):
"""
May not work for all possible widget types for the related field
(simple html form widgets should be okay, we listen to jQuery 'change' event)
"""
related_field = ''
def render(self, name, value, attrs=None, choices=()):
self._element_id = attrs['id']
# normal widget output from the ancestor
# create a field with a dummy name, the real value
# will be retrieved from a hidden field
parent_output = super(AjaxAutoSelect, self).render("dummy-%s" % name, value, attrs, choices)
# output
if value is None:
value = ''
mapping = {
"related_field": self.related_field,
"parent_output": parent_output,
"name": name,
"element_id": self._element_id,
"value": value,
'app_label': self.model._meta.app_label,
'object_name': self.model._meta.object_name,
'select_related': self.select_related,
}
# TO DO:
# we shouldn't SelectBox.empty() if we're editing an existing record that has a value in the related field
output = u"""
<input type="hidden" name="%(name)s" id="hidden-%(element_id)s" value="%(value)s" />
%(parent_output)s
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
SelectBox.init('%(element_id)s');
if (!$('#id_%(related_field)s').val()) {
SelectBox.empty('%(element_id)s');
}
ajax_filtered_fields.bindForeignKeyOptions("%(element_id)s");
$('#id_%(related_field)s').change(function(evt){
ajax_filtered_fields.getForeignKeyJSON('%(element_id)s', '%(app_label)s', '%(object_name)s', '%(related_field)s__pk='+$(evt.target).val(), '%(select_related)s');
});
});
</script>
""" % mapping
return mark_safe(output)
class AjaxFilteredForeignKeyField(forms.ModelChoiceField):
def __init__(self, model, field_name, widget=AjaxAutoSelect, *args, **kwargs):
queryset = model.objects.none()
super(AjaxFilteredForeignKeyField, self).__init__(queryset, widget=widget, *args, **kwargs)
self.isFilteredForeignKeyField = True
self.widget.model = self.model = model
self.widget.related_field = self.related_field = field_name
self.widget.select_related = None
class AjaxFilteredFKFieldsForm(forms.ModelForm):
def __init__(self, initial=None, *args, **kwargs):
super(AjaxFilteredFKFieldsForm, self).__init__(initial=initial, *args, **kwargs)
for field_name in self.fields:
field = self.fields[field_name]
if getattr(field, 'isFilteredForeignKeyField', False):
if field.related_field in self.initial:
# sometimes it's a list with one member, sometimes it's just a number (awesome!)
try:
fk_val = self.initial.get(field.related_field, self.fields[field.related_field].initial)[0]
except TypeError:
fk_val = self.initial.get(field.related_field, self.fields[field.related_field].initial)
fargs = {'%s__pk'%field.related_field: fk_val}
field.queryset = field.model.objects.filter(**fargs)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.