﻿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
35046	BlankChoiceIterator causes AttributeError for some existing packages and projects	Hazho Human	nobody	"The iterators should have method __len__ ...!
while this is not the case for (BlankChoiceIterator) in the current version of Django (5.0), this is why the following error raised:
AttributeError: 'BlankChoiceIterator' object has no attribute '__len__'. Did you mean: '__le__'?


to solve this, simply the BlankChoiceIterator class should have the method __len__ returning 0 as indication for emptiness. 

this is important because the package maintainer or project author may not find the way to update their code accordingly, for example the projects depend on django-countries would have the following trace raised (note there is no obvious indication where in the project code is the main causer that calls __len__ of BlankChoiceIterator objects:


{{{

Traceback (most recent call last):
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\core\handlers\exception.py"", line 55, in inner        
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\core\handlers\base.py"", line 197, in _get_response    
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\django_simple_payment_system\wallets\views.py"", line 38, in index
    return render(request, template_path, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\shortcuts.py"", line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\loader.py"", line 62, in render_to_string     
    return template.render(context, request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\backends\django.py"", line 61, in render      
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 171, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 163, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 1000, in render
    return SafeString("""".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 961, in render_annotated      
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\loader_tags.py"", line 210, in render
    return template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 173, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 163, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 1000, in render
    return SafeString("""".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 961, in render_annotated      
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\defaulttags.py"", line 241, in render
    nodelist.append(node.render_annotated(context))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 961, in render_annotated      
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 1065, in render
    return render_value_in_context(output, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\template\base.py"", line 1042, in render_value_in_context
    value = str(value)
            ^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\forms\utils.py"", line 79, in __str__
    return self.as_widget()
           ^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\forms\boundfield.py"", line 95, in as_widget
    attrs = self.build_widget_attrs(attrs, widget)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\forms\boundfield.py"", line 270, in build_widget_attrs 
    widget.use_required_attribute(self.initial)
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\forms\widgets.py"", line 781, in use_required_attribute
    first_choice = next(iter(self.choices), None)
                             ^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django_countries\widgets.py"", line 29, in get_choices        
    self._choices: ChoiceList = list(self._choices)
                                ^^^^^^^^^^^^^^^^^^^
  File ""C:\env_django_simple_payment_system\Lib\site-packages\django\utils\functional.py"", line 188, in __wrapper__        
    return getattr(result, __method_name)(*args, **kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'BlankChoiceIterator' object has no attribute '__len__'. Did you mean: '__le__'?
}}}


the solution can be as the following:

{{{

# django/utils/choices.py
class BlankChoiceIterator(BaseChoiceIterator):
    """"""Iterator to lazily inject a blank choice.""""""
    # existing code
    
    def __len__(self):
        return 0
}}}

"	Bug	closed	Utilities	5.0	Normal	invalid		Hazho Human Nick Pope Dmytro Litvinov	Unreviewed	0	0	0	0	0	0
