Main Ecosystems
HomePython CorePandas ReferenceNumPy ScientificFastAPI & PydanticDjango Enterprise
More Ecosystems
Environment & SetupRequests & HTTPAsyncIO ConcurrencyObject-Oriented OOPPyTorch Deep LearningScikit-Learn MLFlask FrameworkWeb ScrapingDatabase & ORMDevOps & Docker

ImportError: cannot import name db from partially initialized module app (Circular Import)

Verified FixPython 3.10+Python 3.10+ / Django / FlaskSilo: django

Quick Fix / Solution Rapide

Decouple the database instance into a standalone extensions.py / db.py module, or use the Application Factory pattern to break circular import dependencies.

Root Cause Analysis

This error occurs when Python tries to import a symbol (such as db or models) from a module that is currently in the middle of executing its top-level code, creating a cyclic dependency where module A imports module B which imports module A before module A has finished defining db.

Python's Module Import Lifecycle

When Python imports a module for the first time:

  1. An empty module object is created and inserted into sys.modules.
  2. Python begins executing the module's bytecode line by line from top to bottom.
  3. If line 5 encounters from models import User, execution of app.py pauses and transfers immediately to models.py.
  4. If models.py on line 1 executes from app import db, Python looks up app in sys.modules, finds the partially initialized module object, and checks for db.
  5. Since app.py was paused before reaching the line defining db = SQLAlchemy() or db = Database(), Python raises ImportError: cannot import name 'db' from partially initialized module 'app' (most likely due to a circular import).

Typical Architecture Traps

  • Monolithic app.py importing models.py at top-level while models.py inherits from db.Model defined in app.py.
  • Django apps importing each other's models at module level instead of using string references in ForeignKeys (ForeignKey('app_b.ModelB')).

Reproduction Code (MCVE)

Example: Bug Reproduction
import sys
import types

# Simulates two modules with circular import dependency
mod_app = types.ModuleType('app')
sys.modules['app'] = mod_app  # Registered in sys.modules before 'db' is assigned

# When models attempts to import 'db' from the unpopulated module, ImportError is raised
raise ImportError("cannot import name 'db' from partially initialized module 'app' (most likely due to a circular import)")

Solution 1: Decouple Database Instance into `extensions.py`

Create a separate extensions.py file containing only the unattached extension instance. Both app.py and models.py import from extensions.py, breaking the cycle.

Example: Recommended Solution
class DatabaseExtension:
    def __init__(self):
        self.is_connected = False
        
    def init_app(self, app_config: dict):
        self.is_connected = True
        print(f'Database initialized with: {app_config["DB_URI"]}')

# extensions.py: pure declaration with zero upward dependencies
db = DatabaseExtension()

# models.py imports db from extensions.py without touching app.py
class UserModel:
    def __init__(self, username: str):
        self.username = username

# app.py initializes the extension
db.init_app({'DB_URI': 'sqlite:///:memory:'})
print(f'User model created: {UserModel("alice").username}')

Solution 2: Use String Model References in Django Relationships

In Django models, reference related models using 'app_label.ModelName' strings instead of direct class imports.

Example: Alternative Solution
# In Django models, avoid importing models directly for ForeignKeys:
# Bad: from orders.models import Order; customer = models.ForeignKey(Order, ...)
# Good: customer = models.ForeignKey('orders.Order', ...)

relationship_definition = {
    'model': 'Customer',
    'foreign_key_target': 'orders.Order',
    'status': 'Resolved dynamically at Django app ready phase'
}

print(f'Relationship mapped without circular imports: {relationship_definition}')

Common Pitfalls & Edge Cases

A temporary hack often used is moving import models to the bottom of app.py. While this avoids the crash at import time, it creates fragile code that breaks as soon as a linter (like black or isort) reorders imports to the top of the file. Always use the extensions.py architecture.

Contrasting with related errors:

  • ImportError: cannot import name 'X' from partially initialized module: Circular dependency within project files.
  • ModuleNotFoundError: No module named 'X': Module or file does not exist on sys.path.
  • django.core.exceptions.AppRegistryNotReady: Models imported before Django app registry finishes loading.