Django admin and autocomplete-light - how to override save method

993 views Asked by At

I'm trying to include Django-autocomplete-light in my project. Everything works as expected including the creation of new choice by autocomplete. The only problem is my model contains more than one field and I'm using autocomplete only on the 'name' field. When I save my new record django-admin creates new object with the same name in the database instead of updating the record already created by autocomplete. At the end I have two records, one half empty created by autocomplete, and one valid created by django-admin.

models.py

class Montinent(models.Model):
    name = models.CharField(max_length=250)
    code = models.CharField(max_length=2, unique=True, db_index=True)
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('-name',)

    def __str__(self):
        return self.name

views.py

class MontinentAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        #Don't forget to filter out results depending on the visitor !
        if not self.request.user.is_authenticated():
            return Montinent.objects.none()

        qs = Montinent.objects.all()

        if self.q:
            qs = qs.filter(name__istartswith=self.q)

        return qs

urls.py

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^montinent-autocomplete/$', MontinentAutocomplete.as_view(create_field='name'), name='montinent-autocomplete',),
]

admin.py

class MontinentForm(forms.ModelForm):
    name = forms.ModelChoiceField(
        queryset = Montinent.objects.all(),
        widget = autocomplete.ModelSelect2(url='montinent-autocomplete')
    )

    class Meta:
        model = Montinent
        fields = ['name', 'slug', 'code']


class MontinentAdmin(admin.ModelAdmin):
    form = MontinentForm

admin.site.register(Montinent, MontinentAdmin)

The way autocomplete creates new choice is as follow:

When the user selects that option, the autocomplete script will make a POST request to the view. It should create the object and return the pk, so the item will then be added just as if it already had a PK.

In this case it looks like I need to override the default django-admin save method. I tried just to make the 'name' field unique but in this case Django says this name already exist.

My question is how to override the default save method in my models.py so django to use the returned from autocomplete pk and append the missing information to the row instead of creating new object?

1

There are 1 answers

0
user2263934 On

I was also struggling to fill more than one field with the autocomplete create choice. I needed to include the user who is creating the new entry.

The method that saves the new entry into the database is the create_object(text) method from autocomplete.Select2QuerySetView. You can read more about this method in the documentation http://django-autocomplete-light.readthedocs.io/en/master/api.html

So, to include a user I just override the method as follow:

def create_object(self, text):
    return self.get_queryset().create(**{self.create_field: text, 'user' : self.request.user})

Now you don't need to have partially filled forms using the autocomplete create options. Just fill it with any field you want to.