Once I populated my database with thousands and thousands of rows the
widgets available for manipulating the data on the Admin site became
virtually unusable.

So I have written a custom forms.Field that is a simple TextField that
maps to a (hopefully) unique char field on a Model. The Field
validates that the text maps to a single entry in the model, and
provides a function that can be called from the Form that will reset
the field's initial value to be the unique field (rather than the pk
id).

This has major speed and some usability advantages over the existing
widgets/fields.

It works pretty well, but I'm not so keen on the code and would
appreciate advice for cleaning it up and making it easier to use. I
especially don't like having to call fix_initial_form_value() from the
form. Are there better ways to do this?

Here is the custom Field code, followed by an example using it.

#
# A Field that acts as a TextField but must match an entry in the
given
# queryset/field.
#
class ModelChoiceTextField(forms.Field):
    def __init__(self, model, unique_field_name, attrs=None, *args,
**kwargs):
        kwargs['widget'] = forms.widgets.TextInput(attrs)
        super(ModelChoiceTextField, self).__init__(*args, **kwargs)
        self.queryset = model.objects
        self.unique_field_name = unique_field_name

    def clean(self, value):
        if not value and not self.required:
            return None
        try:
            return self.queryset.get(**{self.unique_field_name: value})
        except self.queryset.model.DoesNotExist:
            raise forms.ValidationError("Please enter a valid %s." %
(self.queryset.model._meta.verbose_name,))
        except self.queryset.model.MultipleObjectsReturned:
            raise forms.ValidationError("Please enter a unique %s." %
(self.queryset.model._meta.verbose_name,))

    #
    # Change the form's intial value for this field to it's chosen
    # member of the object.
    #
    # This assumes the field is for a Foriegn key and the initial
value will
    # be a pk.
    #
    def fix_initial_form_value(self, form, field_name):
        if field_name in form.initial and form.initial[field_name]:
            obj = self.queryset.get(**{'pk': form.initial[field_name]})
            form.initial[field_name] = getattr(obj, self.unique_field_name)

Example usage:

class PackageFileForm(forms.ModelForm):

    file = ModelChoiceTextField(OSFile,
        unique_field_name='file_name',
        attrs={'size':'60'})

    def __init__(self, *args, **kwargs):
        super(ArgusPackageFileForm, self).__init__(*args, **kwargs)

        self.fields['file'].fix_initial_form_value(self, 'file')


I'd also like for the field to set the 'required' flag automagically
based on its field's 'blank' flag. But that may not be doable in the
Field?
Advice, comments and ideas welcome.

Thanks,
Chris Dodd
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to