Opened 4 years ago

Last modified 4 years ago

#16063 new Cleanup/optimization

Problem with searching in m2m fields in inherited model

Reported by: esizikov Owned by: nobody
Component: contrib.admin Version: 1.2
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Django 1.2.5

Models:

class Client(models.Model):
    name = models.CharField(_('name'), max_length=256)
    name2 = models.CharField(_('unofficial or obsolete name'), max_length=256, blank=True, null=True)
    contact_person = models.CharField(_('contact person'), max_length=256, blank=True, null=True)
    ...

class ClientOffice(models.Model):
    name = models.CharField(_('name'), max_length=256)
    name2 = models.CharField(_('unofficial or obsolete name'), max_length=256, blank=True, null=True)
    ...
    client = models.ForeignKey(Client, verbose_name=_('client'))
    ...

and admin options like these:

class ClientAdmin(admin.ModelAdmin):
    search_fields = ('name', 'name2', 'contact_person', 'clientoffice__name', 'clientoffice__name2')
    ...

Numbers:

>>> Client.objects.count()
10907
>>> ClientOffice.objects.count()
16952

Now, if we try searching for clients in admin by a search query containig several words (>3), got django/admin stalled.

The problem is going to be that each word in the search query leads to additional JOIN in final SQL query beacause of qs = qs.filter(...) pattern. The attached patch is for Django 1.2.5, but adopting for the current SVN trunk is trivial.

Attachments (1)

django_1_2_5_admin_search_m2m_prevent_multiple_joining.diff (943 bytes) - added by esizikov 4 years ago.
patch has been made from Mercurial repository

Download all attachments as: .zip

Change History (6)

Changed 4 years ago by esizikov

patch has been made from Mercurial repository

comment:1 Changed 4 years ago by julien

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

This seems related to #13902 and #15819. Are you able to test if this gets fixed by using Django 1.3 or trunk?

comment:2 Changed 4 years ago by aaugustin

  • Needs tests set
  • Triage Stage changed from Unreviewed to Accepted

Looking at the code, the part that is modified by the patch is not modified in current trunk. The problematic pattern is still there:

            for bit in self.query.split():
                ...
                qs = qs.filter(...)

comment:3 Changed 4 years ago by aaugustin

  • Type changed from Bug to Cleanup/optimization

comment:4 Changed 4 years ago by esizikov

I have checked with Django 1.3 and can now confirm that the problem is still there. Django's ORM in 1.3 still generates SELECT with JOIN's for each qs = qs.filter(...) call, which is going to be made per term in a search query.

comment:5 Changed 4 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

Note: See TracTickets for help on using tickets.
Back to Top