Erik Oosterwaal
Erik Oosterwaal

Reputation: 4374

How can I avoid a circular import in this case (Flask and SQLalchemy)?

I have a FLASK application that uses SQLalchemy for the database.

The models are all in models.py, and I have added several properties and methods to the default ORM properties and methods of most model classes. For example; my "contract" model has an extra property contract.first_possible_termination that returns a date.

The problem is that this property accesses a utilities module that has a function to calculate a range of dates. And that function needs to use different configuration options that are stored in the database, in a "configuration" table.

So the utilities module needs to use the ORM models again, to access the Configuration table and thus we have a circular import:

ImportError: cannot import name Configuration

I'm wondering what the standard way is to avoid a circular import here. I imagine more people run into this as one adds methods and properties to ones models.

EDIT, PLEASE NOTE:
I think plantians answer is the best way to go in general, because it promotes SoC, but in my specific case I'm working with a legacy database that has values that influence business rules spread across the different tables in the database.
A lot of the functionality I'm adding to my models will depend in some way or another on these values/business rules, so I will not be able to avoid accessing the database in these functions without refactoring considerably and passing a lot of extra external values to my helper functions.

I can only accept one answer, but both are valid, so an upvote for both, but Blubber's answer is my personal solution for now.
Thanks to both Blubber and Plantian.

Upvotes: 0

Views: 1438

Answers (2)

Ian Wilson
Ian Wilson

Reputation: 9049

Another option is to pass the configuration into the utility function as an argument. Probably best to not have your utilities depend on the model directly. Ie.

def get_range (start_at, strategy):
    pass

Where strategy is detemined by the caller (from the config table). Maybe a code snippet of your util function would be easier to build off of.

Upvotes: 1

Blubber
Blubber

Reputation: 2254

You can import the module inside the function instead of on the top of your module, modules get only imported once, so this shouldn't pose a performance problem.

You can also try to move the configuration module import to the bottom of your util module.

Upvotes: 3

Related Questions