﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
28312	ModelChoiceIterator uses cached length of queryset.	Sjoerd Job Postmus	François Freitag	"In Django 1.8 (but also master), `ModelChoiceIterator` has the following implementation:

{{{
class ModelChoiceIterator:
    def __init__(self, field):
        self.field = field
        self.queryset = field.queryset

    def __iter__(self):
        if self.field.empty_label is not None:
            yield ("""", self.field.empty_label)
        queryset = self.queryset.all()
        # Can't use iterator() when queryset uses prefetch_related()
        if not queryset._prefetch_related_lookups:
            queryset = queryset.iterator()
        for obj in queryset:
            yield self.choice(obj)

    def __len__(self):
        return (len(self.queryset) + (1 if self.field.empty_label is not None else 0))

    def choice(self, obj):
        return (self.field.prepare_value(obj), self.field.label_from_instance(obj))
}}}

As can be seen, `__iter__` actually does a `.all()` to make sure it gets fresh results. However, `__len__` does not. Also: it currently caches all objects inside `self.queryset`, only releasing them again on shutdown which might be problematic if there are a lot of results (or even a few ""large"" results).

Suggested implementation

{{{
def __len__(self):
    return self.queryset.count() + (1 if self.field.empty_label is not None else 0))
}}}"	Bug	closed	Forms	1.8	Normal	fixed			Accepted	1	0	0	0	0	0
