5

I had a problem with an import of an app in another app in my django project. I know there are severals question/asnwsers on this subject, and believe me I read a lot of them, even some about python import.

Here is my project tree (i'll put real folders name):

was/ # full path from my computer /home/user/project/was
....was/ #django project created by django-admin startproject 'was'
    ....manage.py
    ....artists/ #first app
        ....migrations/
        ....templates/
        ....__init__.py 
        ....other_python_files.py
    ....crew/ #second app    
        ....migrations/
        ....templates/
        ....__init__.py
        ....some_files.py
    ....was/ # folder containing settings.py, main urls.py
        ....__init__.py

My first was project (/home/user/project/was) contains the virtualenv generates folders (python3.4).

I checked on my python path sys.path and my project structure in Pycharm and there is /home/user/project/was.

When I do this in PyCharm, I have the autocompletion working fine :

from ..crew.models import MyClass #here i'm in a artists app file

But I get an ValueError :attempted relative import beyond top-level package when import app

And now, same scenario, importing a crew class in artists app but :

from was.crew.models import MyClass

Autocompletion works fine in pycharm but this time I got the classic ImportError : no name was.crew.

I find a solution doing it by adding this line in my settings.py :

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR)) # add this line

Note that BASE_DIR already exist in settings. And now I can do this :

from crew.models import MyClass

And here I got no error (change some settings in Pycharm to have the autocompletion works).

This works, but I really wonder why I have to add this line and why my two first attempt don't work.

I'm a bit lost with package, pythonpath etc (that's why I specified in my schema all __init__.py files).

Shouldn't from ..anotherapp.models import Class works fine without pimping anything in settings.py ?

Whatever, should I keep my solution or is it not a good thing?

Thanks in advance for any response.

PS : note that I already try to had __init__.py files in my first and second was folder, without success.

Bestasttung
  • 2,388
  • 4
  • 22
  • 34

4 Answers4

4

In django projects you do not need to give the path from the root to project directory.Also the BASE_DIR is path to your django project this when you import any app in django you just import it using its name.

So your import will be.

from crew.models import MyClass
Jaysheel Utekar
  • 1,171
  • 1
  • 19
  • 37
  • Yes now i removed the entry in python path (the one i forced) and it works. Don't know why but works fine by writting ```from crew.models import MyClass```. Thanks for your answer. – Bestasttung Jul 23 '15 at 12:14
  • @Bestasttung The pleasure was mine. It works fine because of the BASE_DIR in the settings.py of your django project which maps the path for the django apps. Checkout this django documentation [link](https://docs.djangoproject.com/en/1.8/topics/settings/) – Jaysheel Utekar Jul 23 '15 at 12:37
2

Example project (that works).

Project structure

test_project/
  test_project/
    settings.py
    urls.py
    wsgi.py 
  app1/
    models.py
  app2/
    models.py

app1/models.py

from django.db import models

class Restaurant(models.Model):
    name = models.CharField(max_length=255)

app2/models.py

from django.db import models
from app1.models import Restaurant

class Waiter(models.Model):
    restaurant = models.ForeignKey(Restaurant)
    name = models.CharField(max_length=255)

In your case both from ..crew.models import MyClass and from crew.models import MyClass should work. My guess is that you (or PyCharm) try to run some file or import module when you (or PyCharm) are in app directory. Current directory (whatever it means) should be was (that one created by django-admin.exe. Hope it helps.

f43d65
  • 2,264
  • 11
  • 15
  • the error actually trigger when I launch my server et go to localhost:8000. And yes it should work (actually works in pycharm, it retrives my app trees) but django raise error. Could it be a problem with virtualenv python lib placed too high in folders tree? – Bestasttung Jul 23 '15 at 12:04
  • those i wrotte in my question. Whatever I remove the entry from python path and doing app1.models seems to work without my line in settings. Thanks for your answer ! – Bestasttung Jul 23 '15 at 12:12
0

I think that helps you! I struggled the same problem for couple of days. I had all the init.py files in place. I ended up having to set the sources root to project_dir:

Right-click on project_dir, Mark Directory as > Sources Root

And it helped!

P. Broad
  • 1
  • 1
0

A better approximation of step you can avoid the circular import is to use django.apps.get_model

from django.apps import apps as django_apps

in you code fragment

MyModel = django_apps.get_model("AppName","MyModel")

or

MyModel = django_apps.get_model("AppName.MyModel")

When importing models into another is where you most likely have a circular import, so you can simply avoid importing it and just name it with "AppName.ModelName"

artist = models.ForeignKey("AppName.Artist")