#28312: ModelChoiceIterator uses cached length of queryset.
----------------------------------------------+------------------------
               Reporter:  Sjoerd Job Postmus  |          Owner:  nobody
                   Type:  Bug                 |         Status:  new
              Component:  Uncategorized       |        Version:  1.8
               Severity:  Normal              |       Keywords:
           Triage Stage:  Unreviewed          |      Has patch:  0
    Needs documentation:  0                   |    Needs tests:  0
Patch needs improvement:  0                   |  Easy pickings:  0
                  UI/UX:  0                   |
----------------------------------------------+------------------------
 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))
 }}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28312>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.73d125547a8a71124fc821e4502de92c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to