Loading choices from utils.py results in unexpected error: TypeError: 'CharField' object is not iterable in Django

Question:

I have a models.py file in Django, and it was working perfectly. I have an extensive model named Media, and since it contains quite some Fields with elaborate choices in nested tuples, I decided to move these nested tuples to an utils.py file located in the same app. I found that it is working for all columns in my Media model, except for one. It is shown below:

#This was how it was initially and working:
#Umbrella
UMBRELLA = (
    ("DH", "DH"),
    ("SE", "SE"),
    ("PA", "PA"),
    ("PF", "PF")
)

class Media(models.Model):
umbrella = models.CharField(max_length=20, choices=UMBRELLA, default='Undefined', null=True, blank=True)
second_umbrella = models.CharField(max_length=20, choices=UMBRELLA, default='Undefined', null=True, blank=True) #Problematic?

Changed it to:

utils.py:
#Umbrella
def UMBRELLA():
    UMBRELLA = (
    ("DH", "DH"),
    ("SE", "SE"),
    ("PA", "PA"),
    ("PF", "PF"))
    return(UMBRELLA)

models.py:
from database.utils import *
umbrella=UMBRELLA()

class Media(models.Model):
umbrella = models.CharField(max_length=20, choices=umbrella, default='Undefined', null=True, blank=True) #This one is not problematic
second_umbrella = models.CharField(max_length=20, choices=umbrella, default='Undefined', null=True, blank=True) #This one is problematic

The strange thing here is that if I only change (first) umbrella choiches to umbrella from utils.py it works fine. However, if i change choices from second_umbrella to umbrella from utils.py it crashes?? I meticulously checked the db.sqlite3 with django admin, but the choices are correct in there as originally defined, and exactly similar for both fields (umbrella1 and umbrella2). I can’t understand why it works in one case and not in the other whilst they are exactly similar. It also worked out of the box for all other fields for which I migrated the choices to utils.py. Error prompts on just runserver or makemigrations.

Errorlog:

Traceback (most recent call last):
  File "C:directorymanage.py", line 22, in <module>
    main()
  File "C:directorymanage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocoremanagement__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocoremanagement__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocoremanagementbase.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocoremanagementbase.py", line 443, in execute
    self.check()
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocoremanagementbase.py", line 475, in check
    all_issues = checks.run_checks(
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocorechecksregistry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocorechecksurls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangocorechecksurls.py", line 24, in check_resolver
    return check_method()
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangourlsresolvers.py", line 476, in check
    for pattern in self.url_patterns:
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangoutilsfunctional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangourlsresolvers.py", line 690, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangoutilsfunctional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangourlsresolvers.py", line 683, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:directorydirectoryurls.py", line 21, in <module>
    path('database/', include("database.urls")),
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangourlsconf.py", line 38, in include
    urlconf_module = import_module(urlconf_module)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:directorydatabaseurls.py", line 3, in <module>
    from . import views
  File "C:directorydatabaseviews.py", line 2, in <module>
    from database.forms import MediaForm
packagesdjangoformsmodels.py", line 224, in fields_for_model _C:directorydatabaseforms.py", line 4, in <module>
    formfield = f.formfield(**kwargs)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangoformsmodels.py", line 306, in __new__ibsite-ds = fields_for_model(
packagesdjangodbmodelsfields__init__.py", line 1211, in foribsite-packagesdjangoformsmodels.py", line 224, in fields_for_modelmfield  field = f.formfield(**kwargs)
    return super().formfield(**defaults)                        ibsite-packagesdjangodbmodelsfields__init__.py", line 1211, in formfield
  File "C:UsersMaAppDataLocalProgramsPythonPython310l, in formfield                                                  ibsite-packagesdjangodbmodelsfields__init__.py", line 1026, in formfield
    return super().formfield(**defaults)                        _blank)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangodbmodelsfields__init__.py", line 962, in get_choicesibsite-packagesdjangodbmodelsfields__init__.py", line 1026, in formfield
    defaults["choices"] = self.get_choices(include_blank=includeppDjango_Databasedirectory> _blank)
  File "C:UsersMaAppDataLocalProgramsPythonPython310libsite-packagesdjangodbmodelsfields__init__.py", line 962, in get_choices
    choices = list(self.choices)
TypeError: 'CharField' object is not iterable

Since forms.py is mentioned in the error message I will also post that one:

from django.forms import ModelForm
from database.models import Media

class MediaForm(ModelForm):
    class Meta:
        model = Media
        fields='__all__'

What can I do? I already tried to change the second_umbrella column to another name and make new migration, but the same error remains, and it more seems like a bug somehow than an actual error.

Asked By: Rivered

||

Answers:

I think the over-engineer is the problem, and probablly the choices can’t be dinamically defined, or at least is not kosher
why not use this:

utils.py:
    UMBRELLA = (
    ("DH", "DH"),
    ("SE", "SE"),
    ("PA", "PA"),
    ("PF", "PF"))

models.py:
from database.utils import *

class Media(models.Model):
umbrella = models.CharField(max_length=20, choices=UMBRELLA, default='Undefined', null=True, blank=True) 
second_umbrella = models.CharField(max_length=20, choices=UMBRELLA, default='Undefined', null=True, blank=True)

so import only the constant, and don’t use a innecesary function (and 3 lines less of code)

Answered By: Pablo Estevez