- 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
- Browser-native date input field by kytta 1 month, 1 week ago
- Generate and render HTML Table by LLyaudet 1 month, 2 weeks ago
- My firs Snippets by GutemaG 1 month, 2 weeks ago
- FileField having auto upload_to path by junaidmgithub 2 months, 3 weeks ago
- LazyPrimaryKeyRelatedField by LLyaudet 3 months ago
Comments
Please login first before commenting.