Search code examples
pythonpython-3.xdependency-injectioncircular-dependencypeewee

Python circular imports in class attributes


I have the following files:

user.py

...
from models.company import Company

class User(BaseModel):
    company = ForeignKeyField(Company, ...)
...

company.py

...
from models.user import User

class Company(BaseModel):
    user = ForeignKeyField(User, ...)
...

This is a normal cyclic import error as far as python is concerned. The problem is that the usual workarounds (placing the import statement at the end of the file, importing in different ways, etc...) don't work in this context because I'm using one class in the definition of a class attribute of another class.

What is the proper way to solve the cyclic import error in this context?


Solution

  • It turns out that this is in fact impossible as @PatrickHaugh pointed out:

    Note that you can't define both of these in the same file as they are written. When you execute the first definition, it will fail because the name of the other class hasn't been defined yet, no matter which you define first. What framework is ForeignKeyField from? It may have tools for circumventing this.

    Since i'm using peewee as my ORM, there is a special field built for this pourpose: DeferredForeignKey.

    So, at the end of the day, the solution was:

    user.py

    ...
    from models.company import Company
    
    class User(BaseModel):
        company = ForeignKeyField(Company, ...)
    ...
    

    company.py

    ...
    class Company(BaseModel):
        user = DeferredForeignKey('User', ...)
    ...