24

Mar

Filed in Code, Django |

Today I was creating the submission form for the new iBegin.com homepage. In this we use a lot of JavaScript to make the process more clean. One such use, was an autocomplete on Cities and Categories. To do this, and to keep validation, you need to use a ModelChoiceField, but using a ModelChoiceField with a TextInput doesn’t work. So, I give you an InlineModelChoiceField in Django.

from django import newforms as forms
 
class InlineModelChoiceField(forms.ModelChoiceField):
    def __init__(self, *args, **kwargs):
        kwargs['widget'] = kwargs.pop('widget', forms.widgets.TextInput)
        super(InlineModelChoiceField, self).__init__(*args, **kwargs)
 
    def clean(self, value):
        if not value and not self.required:
            return None
        try:
            return self.queryset.filter(name=value).get()
        except self.queryset.model.DoesNotExist:
            raise forms.ValidationError("Please enter a valid %s." % (self.queryset.model._meta.verbose_name,))
  • Elliott
    That would be AWESOME; thanks for being such a big contributor to OS.
  • I'm using a mootools component, and just a custom view to spit it out. I'm planning out distributing my newfroms utilities here in the near future, which will include some sort of ajax controls.
  • Elliott
    Thanks for this. Its almost exactly what I needed.
    Any chance that you could enlighten us on the auto complete stack that you are using?
  • get_internal_type() is for model fields only (unrelated to newforms);

    I'm actually in need of something similar right now, but I'm not comfortable with using a name string for defining the selection - primarily since I can't guarantee uniqueness. Instead I'm using a hidden field to pass the id, which the JQuery autocomplete widget from bassistance.de supports nicely using the .result() hook (not sure what you are using of course).
  • I don't know much about newforms internals beyond what I've hacked out of it, so you may need get_internal_type (but this works).

    As for the .filter().get() I think I had it doing .filter()[0:1] at first, so that's just a slip on my part.
  • Fidel Ramos
    Very interesting, the flexibility of Django's newforms doesn't cease to amaze me.

    Is this code intended for trunk? Wouldn't you need to define get_internal_type()?

    Also, is there a good reason to use filter(name=value).get() instead of get(name=value)?
blog comments powered by Disqus