Hi François, Thank you for a good write-up of the issue.
Having looked at this from each direction I can't see a way of squaring all the desires here. I see the possibility of an inconsistency between the __len__() and __iter__() calls. This would certainly be nice to avoid but I'm not sure it is the overriding concern here. I can easily see the memory issue being more significant than you're giving it credit for. The original issue (#23623) cited a ≈25% reduction in peak memory usage moving to the iterator. Choices are used in validation and not just template rendering. If not reset, the queryset is retained for the lifetime of the form instance, not just the ModelChoiceIterator iteration. With a large formset, with forms using ModelChoiceField on foreign keys with many thousands of records, the retained queryset would likely add up quickly. As such, I don't think we can just switch the default implementation. (I think we'd quickly see a lot of complaints.) I **do see** the appeal of re-using the queryset for a whole lot of cases. Many times I would trade a bit more memory for the lifetime of a form instance for one less query. (Although, just personally, I'm not sure how often `if field.choices` actually comes up, for me.) So, conclusions (with _I think we should…_ etc elided): * Close your PR as is. https://github.com/django/django/pull/9867 — We can't just change the behaviour. * Look at Tim's PoC PR. https://github.com/django/django/pull/8649 — Can we implement __len__() to not _fetch_all()? Can we implement the custom __bool__ to avoid `count()`? Can we do that without an extra DB query? * If we **can't** avoid the extra query then we have to decide whether it's an acceptable price? * wontfix: If it's not, the existing behaviour is _OK_: it's not incorrect for __len__() to _fetch_all(), and your previous fix makes sure we don't waste that effort if it has been done. * Fix: I'd guess the extra query probably is OK, especially with an optimised __bool__ just checking existence. It's the price of consistency here. * Can we then document, and maybe provide, an alternate ModelChoiceIterator that just re-uses the queryset? * Advantages of this are consistency, fewer DB hits etc. * Cost is the higher memory use. That's my take on the issue thus far. Kind Regards, Carlton -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to firstname.lastname@example.org. Visit this group at https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/f8653583-4d19-4a06-9d68-f81639ea6937%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.