Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django form with ManyToMany field with 500,000 objects times out

Lets say for example I have a Model called "Client" and a model called "PhoneNumbers"

class PhoneNumbers(models.Model):
    number = forms.IntegerField()

class Client(models.Model):
    number = forms.ManyToManyField(PhoneNumbers)

Client has a ManyToMany relationship with PhoneNumbers. PhoneNumbers has almost 500,000 records in it so when it comes to editing a Client record from a model form with a MultiSelect widget that comes with a M2M filed, it takes forever to load. In fact, it never does. It just sits there trying to load all of those phone objects I am assuming.

My workaround was to so some tedious things with ajax and jquery to edit only the phone numbers in a Client record. Before wasting my time with all of that I wanted to see if there is somehow another way to go about it without having my page hang.

like image 868
Austin Avatar asked May 10 '13 14:05

Austin


2 Answers

You need to create a custom widget for this field that lets you autocomplete for the correct record. If you don't want to roll your own: http://django-autocomplete-light.readthedocs.io/

I've used this for its generic relationship support, the M2M autocomplete looks pretty easy and intuitive as well. see video of use here: http://www.youtube.com/watch?v=fJIHiqWKUXI&feature=youtu.be

After reading your comment about needing it outside the admin, I took another look at the django-autocomplete-light library. It provides widgets you can use outside the admin.

from dal import autocomplete
from django import forms

class PersonForm(forms.ModelForm):
    class Meta:
        widgets = {
            'myformfield': autocomplete.ModelSelect2(
                # ...
            ),
        }
like image 124
Francis Yaconiello Avatar answered Oct 19 '22 18:10

Francis Yaconiello


Since Django 2.0, Django Admin ships with an autocomplete_fields attribute that generates autocomplete widgets for foreign keys and many-to-many fields.

class PhoneNumbersAdmin(admin.ModelAdmin):
    search_fields = ['number']

class ClientAdmin(admin.ModelAdmin):
    autocomplete_fields = ['number']

Note that this only works in the scope of Django admin of course. To get autocomplete fields outside the admin you would need an extra package such as django-autocomplete-light as already suggested in other answers.

like image 6
Antoine Pinsard Avatar answered Oct 19 '22 19:10

Antoine Pinsard