#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.