#29158: ModelChoiceField crashes when checking choices' length
-------------------------------------+-------------------------------------
               Reporter:  François   |          Owner:  François Freitag
  Freitag                            |
                   Type:             |         Status:  assigned
  Uncategorized                      |
              Component:  Forms      |        Version:  1.8
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 ModelChoiceField must accept Manager as a `.queryset` for backward
 compatibility reasons (see #25683). However, `ModelChoiceIterator` does
 not play nice with Managers:


 {{{
 class TestModelChoiceField(TestCase):
     def test_queryset_manager_has_length(self):
         f = ModelChoiceField(ChoiceOptionModel.objects)
         len(f.choices)
 }}}

 Errors with:

 {{{
 ======================================================================
 ERROR: test_queryset_manager_has_length
 (forms_tests.test_tmp.TestModelChoiceField)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "django/tests/forms_tests/test_tmp.py", line 10, in
 test_queryset_manager_has_length
     len(f.choices)
   File "django/django/forms/models.py", line 1141, in __len__
     return len(self.queryset) + (1 if self.field.empty_label is not None
 else 0)
 TypeError: object of type 'Manager' has no len()
 }}}

 ----

 The reason why this `TypeError` was not reported earlier is probably
 because Python swallows `TypeError` silently for `__len__` when `list` is
 called, because generators have no `len`:

 {{{
 Python 3.6.4 (default, Jan  5 2018, 02:35:40)
 [GCC 7.2.1 20171224] on linux
 Type "help", "copyright", "credits" or "license" for more information.
 >>> def gene():
 ...     yield 1
 ...
 >>> len(gene())
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: object of type 'generator' has no len()
 >>> list(gene())
 [1]

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29158>
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/058.3003c1605dda325bb31676e58323b746%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to