Search code examples
djangodjango-formsdjango-admin

I need a "raw id" widget for a ModelMultipleChoiceField


one of my models has a ManyToMany field. I'm using a ModelMultipleChoiceField with the default widget (SelectMultiple widget) at the form.

The problem: There are about 50k options for this field and it's taking ages to load.

I want to change the widget to CharField and enter each PK separated by a comma (like the admin raw_id_field).

Questions: What is the best approach to do this? Did somebody already do a widget for this? Shoul I create my own Widget or Field?

Thanks!


Solution

  • If you don't need selection of items in separate window, like in admin, then writing such widget is quite simple. With following widget you will be able to enter comma-separated list of pks:

    from django import forms
    from django.utils.encoding import force_text
    
    class ModelMultiRawInput(forms.TextInput):
        def render(self, name, value, attrs=None):
            if value:
                value = ','.join([force_text(v) for v in value])
            else:
                value = ''
            return super(ModelMultiRawInput, self).render(name, value, attrs)
    
        def value_from_datadict(self, data, files, name):
            value = data.get(name)
            if value:
                return value.split(',')
    

    You would normally use this widget like that:

    class MyForm(forms.Form):
        users = forms.ModelMultipleChoiceField(queryset=User.objects.all(), widget=ModelMultiRawInput)