#31295: required ModelChoiceField makes duplicate (cursor) queries to the 
database
-------------------------------------+-------------------------------------
     Reporter:  Aurélien Pardon      |                    Owner:  nobody
         Type:                       |                   Status:  closed
  Cleanup/optimization               |
    Component:  Forms                |                  Version:  2.2
     Severity:  Normal               |               Resolution:  needsinfo
     Keywords:  Model                |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Aurélien Pardon):

 Replying to [comment:6 Carlton Gibson]:
 > I don't know what else I can say. It's part of the design of
 ModelChoiceField that it re-evaluates it's queryset each time it's
 iterated.

 {{{ModelChoiceField}}} iterates over his {{{ModelChoiceIterator}}} when
 rendering its widget (and its options).
 {{{ModelChoiceIterator}}} does not necessarily re-evaluates it's queryset
 each time it's iterated: sometimes the query is cached (for example when
 the query involves a {{{prefetch_related}}}), sometimes it is not cached.

 The reason {{{ModelChoiceIterator}}} use, sometimes, {{{.iterator()}}} is
 for '''performance''' (less memory usage, see #3534) and because, at the
 times, the queryset was evaluated/fetched only once when the the field was
 rendered.
 After [https://code.djangoproject.com/ticket/27370 Django's Select widget
 adds a required="required" attribute, even if created with
 empty_label=True], the queryset is evaluated/fetched twice because of the
 new {{{.use_required_attribute}}} method.


 > See #3534 for example, 13 years ago:
 > > ModelChoiceField and ModelMultipleChoiceField cache the output of
 their queryset the first time self.choices is accessed. This is bad for
 long-running processes, such as mod_python, because the cache gets stale.
 Plus, it's bad saving all of those choices in memory. The attached unit
 tests illustrate the problem.
 > The exact same memory usage considerations were the motivation for the
 move to iterator() in #23623. I can't see that being removed.

 You said that "correctness trumps performance" but since
 [https://code.djangoproject.com/ticket/27370], the usage of
 {{{.iterator()}}} in ModelChoiceIterator '''with''' the new
 {{{.use_required_attribute}}} when rendering the form leads to invalid
 HTML. How is this not a bug?
 Moreover, how duplicate requests to the database (the second one is
 useless and leads to bug) do not fall under the same performance
 considerations of #3534?


 I think the solution is to decide to use the required attribute after
 having rendered the field options: while iterating the choices/options, we
 can check if the first option allows us to use the required attribute.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31295#comment:7>
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 unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/065.28842282379cd9e7bff4533a3c4f95b9%40djangoproject.com.

Reply via email to