Circular import when importing edit handlers on custom User model file
See original GitHub issueI have an application using a custom user model, and I want to provide an alternative admin with the ModelAdmin. However,
Steps to Reproduce
- Create any application using a custom user model.
- Try to import FieldPanel on the same file as the custom user model.
- An ImportError will be raised as the server starts. FieldPanel can’t be imported on that file because admin/models.py imports the edit handlers, which import all of the forms from Wagtail Admin, which import Django’s AuthenticationForm and PasswordResetForm from django/contrib/auth/forms.py, which in gets the user model, so there’s some sort of circular import.
Full trace:
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7fd0f41be1e0>
Traceback (most recent call last):
File "virtualenv_route/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "virtualenv_route/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
autoreload.raise_last_exception()
File "virtualenv_route/lib/python3.6/site-packages/django/utils/autoreload.py", line 251, in raise_last_exception
six.reraise(*_exception)
File "virtualenv_route/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "virtualenv_route/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
fn(*args, **kwargs)
File "virtualenv_route/lib/python3.6/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "virtualenv_route/lib/python3.6/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models()
File "virtualenv_route/lib/python3.6/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "virtualenv_route/lib/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "virtualenv_route/lib/python3.6/site-packages/wagtail/admin/models.py", line 5, in <module>
from wagtail.admin import edit_handlers # NOQA
File "virtualenv_route/lib/python3.6/site-packages/wagtail/admin/edit_handlers.py", line 24, in <module>
from .forms import ( # NOQA
File "virtualenv_route/lib/python3.6/site-packages/wagtail/admin/forms.py", line 5, in <module>
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
File "virtualenv_route/lib/python3.6/site-packages/django/contrib/auth/forms.py", line 22, in <module>
UserModel = get_user_model()
File "virtualenv_route/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 194, in get_user_model
return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
File "virtualenv_route/lib/python3.6/site-packages/django/apps/registry.py", line 203, in get_model
app_config.import_models()
File "virtualenv_route/lib/python3.6/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "virtualenv_route/lib/python3.6/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "myapp/web/app/accounts/models.py", line 6, in <module>
from wagtail.admin.edit_handlers import FieldPanel, FieldRowPanel
ImportError: cannot import name 'FieldPanel'
Workaround
In this case I solved it by specifying panels directly in get_edit_handler method of a custom UserEditView and specifying edit_view_class on the custom UserAdmin.
Technical details
Wagtail 2.0.1
Issue Analytics
- State:
- Created 5 years ago
- Reactions:3
- Comments:8
Top Results From Across the Web
Simple Workaround to Avoid Django Circular Import Errors
In some cases, application models need to reference each other dependently—this can lead to a circular import error. Fortunately, Django has an ...
Read more >ImportError: cannot import name '...' from partially initialized ...
A similar error with the message "most likely due to a circular import" would occur. The same contents would work fine if I...
Read more >Importing settings in a module that contains a logging Handler ...
Importing settings in a module that contains a logging Handler causes circular import. Reported by: donspaulding, Owned by: Claude Paroz <claude@…>.
Read more >Python Circular Import Problem and Solutions
As python prefers importing from the local current directory first and then from site-packages, it will create a circular import problem.
Read more >Handling circular dependencies - Cloud - 8.0
To fix the data model in such a case, simply turn ... ... Importing user-defined indicators from a csv file (deprecated feature) ·...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Have made an attempt to fix this, by splitting up
wagtail.admin.forms
into submodules and only importing the relevant submodule where possible (so thatwagtail.admin.edit_handlers
can import the model-form-hacking stuff without also importing the auth forms): https://github.com/gasman/wagtail/tree/admin-forms-circular-dependencyI’m not totally happy with the result, though: I was hoping we could keep it fully backwards-compatible (i.e. allow all existing
from wagtail.admin.forms import ...
lines to continue working) by retaining all the imports inwagtail/admin/forms/__init__.py
, but this file will also get imported onfrom wagtail.admin.forms.models import ...
, so the circular reference still remains 😦. The only way forward I can see (aside from horrible things like putting the new submodules in a new namespace likewagtail.admin.forms2
) is to remove the import of thewagtail.admin.forms.auth
forms fromwagtail.admin.forms
.Technically, the only documented things in
wagtail.admin.forms
(and thus the only things we’re duty-bound to keep in their current locations) areWagtailAdminModelForm
andWagtailAdminPageForm
. In practice, I expect that a lot of external code is importingSearchForm
(because they’re copying what wagtailimages / wagtaildocs / contrib apps do) and I wouldn’t be surprised to find that there are third-party apps subclassingLoginForm
to do custom authentication (2FA or whatever).So, anyone know any clever tricks for defining a bunch of things in
wagtail.admin.forms
without the whole lot getting imported duringfrom wagtail.admin.forms.models import FooForm
?Thanks for the report @rafaponieman! Please can you provide an example models.py file that reproduces this issue, starting from a new Wagtail project?