2

In a Django project, I need to import class-A from file-1 in file-2. and import class-B from file-2 in file-1.

These classes have their unique methods, and I want to use these methods within another file (like description above).

I'm working with:

Python 3.8.10 (within a virtual environment)

Windows 10 - 64 bit (latest build)

Django 4.0.4

When I runpython manage.py runserver, I see errors below:

(my_ea_proj) PS F:\my_ea_proj\ea_proj> python.exe .\manage.py runserver
Traceback (most recent call last):
  File ".\manage.py", line 30, in <module>
    main()
  File ".\manage.py", line 13, in main
    django.setup()
  File "F:\my_ea_proj\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "F:\my_ea_proj\lib\site-packages\django\apps\registry.py", line 116, in populate
    app_config.import_models()
  File "F:\my_ea_proj\lib\site-packages\django\apps\config.py", line 304, in import_models
    self.models_module = import_module(models_module_name)
  File "C:\Python38\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "F:\my_ea_proj\ea_proj\ea_app\models.py", line 16, in <module>
    from .login_request_based import full_request
  File "F:\my_ea_proj\ea_proj\ea_app\login_request_based.py", line 10, in <module>
    from ea_app.all_utils.ea_utils import ea_utils_class
  File "F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py", line 10, in <module>
    from ea_app.login_request_based import full_request
ImportError: cannot import name 'full_request' from partially initialized module 'ea_app.login_request_based' (most likely due to a circular import) (F:\my_ea_proj\ea_proj\ea_app\login_request_based.py)
F:\my_ea_proj\ea_proj>tree /F
F:.
│   manage.py
│   __init__.py
│
├───ea_app
│   │   admin.py
│   │   apps.py
│   │   login_request_based.py
│   │   models.py
│   │   tasks.py
│   │   tests.py
│   │   urls.py
│   │   views.py
│   │   __init__.py
│   │
│   ├───all_utils
│   │       ea_remote_db.py
│   │       ea_utils.py
│   │       __init__.py
│   │
│   ├───migrations
│   │       __init__.py
│   |       ...skipped other migration files...
│
└───ea_proj
        asgi.py
        settings.py
        urls.py
        wsgi.py
        __init__.py

When I add below classes in ea_utils.py and login_request_based.py files, I got error ImportError: cannot import name 'full_request' from partially initialized module 'ea_app.login_request_based' (most likely due to a circular import).... But when I comment-out one of them, problem fixed and built-in web server is launched successfully.

F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py:
from ea_app.login_request_based import full_request

F:\my_ea_proj\ea_proj\ea_app\login_request_based.py
from ea_app.all_utils.ea_utils import ea_utils_class

How to fix this issue?.

Thank you @mohamed-beltagy. but your comment/link didn't fix my problem. Please read note below.

What happens when using mutual or circular (cyclic) imports in Python?

If you do import foo (inside bar.py) and import bar (inside foo.py), it will work fine. By the time anything actually runs, both modules will be fully loaded and will have references to each other.

The problem is when instead you do from foo import abc (inside bar.py) and from bar import xyz (inside foo.py). Because now each module requires the other module to already be imported (so that the name we are importing exists) before it can be imported.

Note, if you do from foo import * and from bar import *, everything executed in the foo is in the initializing phase of bar, and the actual functions in bar has not yet been defined...

ali reza
  • 141
  • 3
  • 13

4 Answers4

4

If in one of the modules you import a model only to make a relation to it, e.g.:

from characters.models import Character

class Inventory(models.Model):
    character = models.OneToOneField(Character, on_delete=models.CASCADE, related_name='inventory')

You can do this and so remove the import at the beginning:

#from characters.models import Character  # Becomes useless

class Inventory(models.Model):
    character = models.OneToOneField('characters.Character', on_delete=models.CASCADE, related_name='inventory')
GuiTeK
  • 1,561
  • 5
  • 20
  • 39
  • thanks you. but those are python files and not related to Django Models (those extra functions are used in Django model/admin/view files. for short time, I redefined all functions in a python class. but i want to have them in separated files. – ali reza Oct 30 '22 at 09:08
0

I was facing the same issue with the following file structure:

├───models
│   │   app_1.py
│   │   __init__.py # (will refer to this as models.init)
│   │
│   ├───engines
│   │       app_2.py
│   │       __init__.py

So, in models.init i had a instance from app_2 like this

from models.engines.app_2 import app2_class
new_app = app2_class()
new_app.do_something()

In my app_1 module i had these imports:

from models import new_app

In my app_2 module i had these imports:

from models.app_1 import app1_class

I tried several workarounds but none worked for me, but i was able to get rid of the error and get all classes and the instance in models.init to work properly. This is the final solution i got around. No change in models.init as i need to access it. No change in app_2 also.

In my app_1 module i modified to this:

import models

    # Somewhere in the code, I went with
    models.new_app.do_something_different()

Hope this works for you.

n1klaus
  • 19
  • 5
0

I had a very similar problem, ironically, I separated the classes I needed to import into a separate models file (models_3.py), and importing from there worked for me, I still don't know why this happens, because I have other models. they work this way, but there seem to be specific cases.

Old structure:

├───app
│   │   models_1.py
│   ├   models_2.py
│   │   __init__.py

new structure:

├───app
│   │   models_1.py
│   ├   models_2.py
│   ├   models_3.py
│   │   __init__.py
LuisFerchx
  • 37
  • 8
0

I don't know my new solution is a trick or is a principle of Python in Django framework.

  • Django==4.0.X or 3.2.X
  • Python=3.8.10
  • windows==10 x64 (latest build)

Pleas look carefully to the output of the my command in question (F:\my_ea_proj\ea_proj>tree /F). and read my question carefully.

When i add the from ea_app.models import BotReport in file ea_utils.py, within main python block (next to the lines are related to the import ... or from ... import ...), I got error below:

.....skipped.....
File "F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py", line 50, in module
from ea_app.models import BotReport ImportError: cannot import name 'BotReport' from partially initialized module 'ea_app.models'
(most likely due to a circular import) (F:\my_ea_proj\ea_proj\ea_app\models.py)

but when i add the from ea_app.models import BotReport in method's section of class(es), everything works fine without any problem. for example:

class EA_UTILS_CLASS (object):
    def get_transfers (self,  bot_id: int):
        from ea_app.models import BotReport
        ....skipped....
        ....skipped....
        tmpObj = BotReport.objects.get (id=bot_id)
        tmpObj.transfer.create(.........)

I hope my solution help to others Django+Python developers.

Have great times ;X

ali reza
  • 141
  • 3
  • 13