Opened 2 years ago
Last modified 2 years ago
#34807 closed Bug
importing `django.forms` causes circular import error — at Initial Version
| Reported by: | Collin Anderson | Owned by: | nobody |
|---|---|---|---|
| Component: | Forms | Version: | dev |
| Severity: | Release blocker | Keywords: | |
| Cc: | Nick Pope | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
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`.