Managing all modules imports in a single file in Python/Django project, while avoiding circular imports
I’m working on a Django project that has numerous imported modules across various files, sometimes totaling up to 50 lines of imports per page. To reduce cluttering, I created a single file, "imports.py", to centralize my imports.
Here’s a brief example of what it looks like:
from datetime import date, datetime
from typing import Any, Callable, Optional, Final, Type, TypeAlias, cast, Iterable
from functools import wraps
from cryptography.fernet import Fernet
from requests.auth import HTTPBasicAuth
from requests.models import Response
from PIL import Image, UnidentifiedImageError
from smtplib import SMTPRecipientsRefused
from dotenv import load_dotenv
from django.db import models, IntegrityError
...
# a lot more
__all__ = [
'datetime', 'Any',
'Callable', 'Optional', 'Final', 'Type', 'TypeAlias', 'cast', 'Iterable', 'wraps',
'Fernet', 'HTTPBasicAuth', 'Response', 'Image', 'UnidentifiedImageError',
'SMTPRecipientsRefused', 'load_dotenv', 'models', 'IntegrityError',......]
Then, in other files, I import everything from imports.py like this:
from bi_app.py.imports import *
While I know this might be unconventional, I find it more organized. This method works well for external modules and also for Linters, but when I try to include imports for my own project files, I often run into circular import issues.
My question is: Is there a way to combine all imports from my own files, into a single file without causing circular imports? Thanks for your help
I think to accommodate this import approach, you'd have to carefully architect the whole structure of your project around it. For example if you had (say) 10 modules total, where 7 of them are independent bottom-level modules requiring no imports at all, and the other 3 require importing only those 7 bottom-level modules but do not require importing from each other. Which is pretty darn difficult in Django, with all the interaction needed between your models.py
, urls.py
, and views.py
... they each rely on elements of the others.
I get the appeal of this approach but accommodating it in a large and complex project might be more effort than it's worth. Your best bet would be to restrict the "importer module" to those elements you mentioned which don't step on each other (externals etc.) and then use the more conventional approach for any modules imported from your own project. You'll still get the benefit of having most(?) of that very long list of imports consolidated in one place.