﻿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
34807	importing `django.forms` causes circular import error	Collin Anderson	nobody	"circular import between forms and models and choices.

before [500e01073adda32d514962] you could import forms just fine.

{{{
git checkout 500e01073adda32d514962^
python3 -c""from django.db import models""  # works fine
python3 -c""from django import forms""  # works fine
}}}


but since [500e01073adda32d514962] this hasn't worked due to circular import.

{{{
git checkout 500e01073adda32d514962
python3 -c""from django.db import models""  # works fine
python3 -c""from django import forms""  # fails:

Traceback (most recent call last):
  File ""<string>"", line 1, in <module>
  File ""django/forms/__init__.py"", line 6, in <module>
    from django.forms.boundfield import *  # NOQA
  File ""django/forms/boundfield.py"", line 5, in <module>
    from django.forms.widgets import MultiWidget, Textarea, TextInput
  File ""django/forms/widgets.py"", line 15, in <module>
    from django.utils.choices import normalize_choices
  File ""django/utils/choices.py"", line 3, in <module>
    from django.db.models.enums import ChoicesMeta
  File ""django/db/models/__init__.py"", line 3, in <module>
    from django.db.models.aggregates import *  # NOQA
  File ""django/db/models/aggregates.py"", line 5, in <module>
    from django.db.models.expressions import Case, Func, Star, Value, When
  File ""django/db/models/expressions.py"", line 12, in <module>
    from django.db.models import fields
  File ""django/db/models/fields/__init__.py"", line 18, in <module>
    from django.utils.choices import CallableChoiceIterator, normalize_choices
ImportError: cannot import name 'CallableChoiceIterator' from partially initialized module 'django.utils.choices' (most likely due to a circular import) (django/utils/choices.py)

python3 -c""from django.utils import choices"" # also fails:

Traceback (most recent call last):
  File ""<string>"", line 1, in <module>
  File ""django/utils/choices.py"", line 3, in <module>
    from django.db.models.enums import ChoicesMeta
  File ""django/db/models/__init__.py"", line 3, in <module>
    from django.db.models.aggregates import *  # NOQA
  File ""django/db/models/aggregates.py"", line 5, in <module>
    from django.db.models.expressions import Case, Func, Star, Value, When
  File ""django/db/models/expressions.py"", line 12, in <module>
    from django.db.models import fields
  File ""django/db/models/fields/__init__.py"", line 10, in <module>
    from django import forms
  File ""django/forms/__init__.py"", line 6, in <module>
    from django.forms.boundfield import *  # NOQA
  File ""django/forms/boundfield.py"", line 5, in <module>
    from django.forms.widgets import MultiWidget, Textarea, TextInput
  File ""django/forms/widgets.py"", line 15, in <module>
    from django.utils.choices import normalize_choices
ImportError: cannot import name 'normalize_choices' from partially initialized module 'django.utils.choices' (most likely due to a circular import) (django/utils/choices.py)
}}}

Models has always had a dependency on Forms, but now Models depends on Forms depends on `utils.choices` which depend on `models.enums.ChoicesMeta`

Summary of the circle: `django.forms` -> `forms.widgets` -> `django.utils.choices` -> `django.db.models.enums` -> `models.__init__` -> `models.aggregates` -> `models.fields` -> `django.forms`.

If `django.db.models` is imported before forms then it happens to import fine because the order of imports happens to lines up perfectally, but it's very very fragile. `models.__init__` -> `models.aggregates` -> `models.fields`  -> `django.forms` -> `forms.widgets` -> `django.utils.choices` -> `django.db.models.enums`.



"	Bug	new	Forms	dev	Release blocker				Accepted	0	0	0	0	0	0
