#18597: `BaseInlineFormSet` should attempt to get it's queryset from it's
instance
related manager before falling back to it's model's default manager
-------------------------------------+-------------------------------------
Reporter: charettes | Owner: nobody
Type: | Status: new
Cleanup/optimization | Version: 1.4
Component: Forms | Resolution:
Severity: Normal | Triage Stage:
Keywords: model formset | Unreviewed
inline | Needs documentation: 0
Has patch: 1 | Patch needs improvement: 0
Needs tests: 1 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Description changed by aaugustin:
Old description:
> The newly introduced `prefetch_related` method can be quite handy to
> avoid unnecessary queries (thanks Luke :), however it's quite useless
> when used with `BaseInlineFormSet` since
> [https://github.com/django/django/blob/4a103086d5c67fa4fcc53c106c9fdf644c742dd8/django/forms/models.py#L694
> it won't even try to get its needed `queryset` from the related manager].
>
> i.e.
> {{{#!python
> from django.db import models
>
> class Author(models.Model):
> name = models.CharField(max_length=255)
>
> class Book(models.Model):
> name = models.CharField(max_length=255)
> author = models.ForeignKey(Author, related_name='books')
>
> class Meta:
> # Needed because `BaseModelFormSet.get_query_set` wants an
> ordered set or issue another query
> ordering = ('pk',)
> }}}
>
> {{{
> In [1]: from django.conf import settings
>
> In [2]: from django.db import connection
>
> In [3]: from library.models import *
>
> In [4]: from django.forms.models import inlineformset_factory
>
> In [5]: a = Author.objects.create(name='David Abram')
>
> In [6]: b1 = Book.objects.create(name='Becoming Animal', author=a)
>
> In [7]: b2 = Book.objects.create(name='The Spell of the Sensuous',
> author=a)
>
> In [8]: BookInlineFormSet = inlineformset_factory(Author, Book)
>
> In [9]: settings.DEBUG = True
>
> In [10]: instance = Author.objects.prefetch_related('books').get()
>
> In [11]: BookInlineFormSet(instance=instance)
> Out[11]: <django.forms.formsets.BookFormFormSet at 0x3c68d50>
>
> In [12]: print connection.queries
> [{u'time': u'0.000', u'sql': u'SELECT "library_author"."id",
> "library_author"."name" FROM "library_author"'}, {u'time': u'0.000',
> u'sql': u'SELECT "library_book"."id", "library_book"."name",
> "library_book"."author_id" FROM "library_book" WHERE
> "library_book"."author_id" IN (1) ORDER BY "library_book"."id" ASC'},
> {u'time': u'0.000', u'sql': u'SELECT "library_book"."id",
> "library_book"."name", "library_book"."author_id" FROM "library_book"
> WHERE "library_book"."author_id" = 1 ORDER BY "library_book"."id" ASC'}]
> }}}
>
> I guess it's only a matter of time before people start trying to optimize
> their formsets (or their `ModelAdmin` by overriding `get_queryset`) and
> stumble on this ''limitation''.
>
> I've written a patch (I'll create a pull request) for which I'll write
> tests if this optimization is ''Accepted''.
New description:
The newly introduced `prefetch_related` method can be quite handy to avoid
unnecessary queries (thanks Luke :), however it's quite useless when used
with `BaseInlineFormSet` since
[https://github.com/django/django/blob/4a103086d5c67fa4fcc53c106c9fdf644c742dd8/django/forms/models.py#L694
it won't even try to get its needed `queryset` from the related manager].
i.e.
{{{#!python
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=255)
class Book(models.Model):
name = models.CharField(max_length=255)
author = models.ForeignKey(Author, related_name='books')
class Meta:
# Needed because `BaseModelFormSet.get_query_set` wants an ordered
set or issue another query
ordering = ('pk',)
}}}
{{{
In [1]: from django.conf import settings
In [2]: from django.db import connection
In [3]: from library.models import *
In [4]: from django.forms.models import inlineformset_factory
In [5]: a = Author.objects.create(name='David Abram')
In [6]: b1 = Book.objects.create(name='Becoming Animal', author=a)
In [7]: b2 = Book.objects.create(name='The Spell of the Sensuous',
author=a)
In [8]: BookInlineFormSet = inlineformset_factory(Author, Book)
In [9]: settings.DEBUG = True
In [10]: instance = Author.objects.prefetch_related('books').get()
In [11]: BookInlineFormSet(instance=instance)
Out[11]: <django.forms.formsets.BookFormFormSet at 0x3c68d50>
In [12]: print connection.queries
[{u'time': u'0.000', u'sql': u'SELECT "library_author"."id",
"library_author"."name" FROM "library_author"'},
{u'time': u'0.000', u'sql': u'SELECT "library_book"."id",
"library_book"."name", "library_book"."author_id" FROM "library_book"
WHERE "library_book"."author_id" IN (1) ORDER BY "library_book"."id"
ASC'},
{u'time': u'0.000', u'sql': u'SELECT "library_book"."id",
"library_book"."name", "library_book"."author_id" FROM "library_book"
WHERE "library_book"."author_id" = 1 ORDER BY "library_book"."id" ASC'}]
}}}
I guess it's only a matter of time before people start trying to optimize
their formsets (or their `ModelAdmin` by overriding `get_queryset`) and
stumble on this ''limitation''.
I've written a patch (I'll create a pull request) for which I'll write
tests if this optimization is ''Accepted''.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/18597#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.