3

In a Django project, I have a directory structure that looks something like this:

project/
├╴module_name/
│ ├╴dbrouters.py
│ ...
...

In dbrouters.py, I define a class that starts out like this:

class CustomDBRouter(object):
  current_connection = 'default'
  ...

The idea is to have a database router that sets the connection to use at the start of each request and then uses that connection for all subsequent database queries similarly to what is described in the Django docs for automatic database routing.

Everything works great, except that when I want to import CustomDBRouter in a script, I have to use the absolute path, or else something weird happens.

Let's say in one part of the application, CustomDBRouter.current_connection is changed:

import project.module_name.dbrouters.CustomDBRouter
...
CustomDBRouter.current_connection = 'alternate'

In another part of the application (assume that it is executed after the above code), I use a relative import instead:

import .dbrouters.CustomDBRouter
...
print CustomDBRouter.current_connection # Outputs 'default', not 'alternate'!

I'm confused as to why this is happening. Is Python creating a new class object for CustomDBRouter because I'm using a different import path?

Bonus points: Is there a better way to implement a 'global' class property?

  • 1
    Related Reading: https://ncoghlan_devs-python-notes.readthedocs.org/en/latest/python_concepts/import_traps.html – torek Jul 26 '13 at 20:45

2 Answers2

0

It depends on how this script is being executed. When you're using relative imports, you have to make sure the name of the script the import is in has a __name__ attribute other than __main__. If it does, import .dbrouters.CustomDBRouter becomes import __main__.dbrouters.CustomDBRouter.

I found this here.

Community
  • 1
  • 1
smakateer
  • 556
  • 4
  • 5
0

It turns out, the problem was being caused by a few lines in another file:

PROJECT_ROOT = '/path/to/project'
sys.path.insert(0, '%s' % PROJECT_ROOT)
sys.path.insert(1, '%s/module_name' % PROJECT_ROOT)

The files that were referencing .dbrouters were imported using the "shortcut" path (e.g., import views instead of import module_name.views).