Cannot import models from another app in Django
Asked Answered
O

9

30

so I have 2 apps running in the same project.

My files are structured as follows:

/project_codebase
    /project
        __init.py
        settings.py
        urls.py
        wsgi.py
        ...    
    /app1
        ...
    /app2
        ...
    manage.py

So, I for some weird reason have a different name for my base directory (that is, it ends with codebase). Hopefully, that is not an issue.

In my settings.py, I have this:

INSTALLED_APPS = [
    ...

    'app1',
    'app2',
]

Ok, so in my models.py (from app2), I can easily import models from app1 with from app1.models import *, however, when I use from app2.models import * in my models.py (from app1), I get an ImportError.

Any solutions to this?

Occultation answered 8/5, 2017 at 12:2 Comment(3)
May be it is due to circular dependency. #744873Playreader
Well, you've created a circular import dependency. Why do you need to import each app's models into the other?Moussaka
You should accept an answer.Southeastward
J
67

This might be due to circular import issues. To avoid this you should load the model dynamically:

For recent versions of django (1.7+) use the application registry:

from django.apps import apps
MyModel1 = apps.get_model('app1', 'MyModel1')

For earlier django versions (<1.7):

from django.db.models.loading import get_model
MyModel1 = get_model('app1', 'MyModel1')

Note 1: If you want to define a ForeignKey relationship, there is no need for a separate import statement. Django has you covered on this:

If app1 is an installed app, you should define the ForeignKey relationship as follows:

# in app2.py
class MyModel2(models.Model):
   mymodel1 = models.ForeignKey('app1.MyModel1')

Note 2: The get_model only works if app1 is an installed app and MyModel1 is the model you want to import from app1.

Note 3: Try to avoid wildcard import (from ... import *), as this is bad practice.

Jeremyjerez answered 8/5, 2017 at 12:7 Comment(3)
Why django switched to that kind of import. Previously we used to import models as "import"Maple
@ilyasJumadurdyew this is mainly to avoid circular imports that would happen when the modules are loaded using the 'traditional' import statement. Using get_model or the above shown foreignkey definition imports the models on runtime only, once all modules are loaded.Jeremyjerez
"Note 1" will help someone cross-linking models in Django with this a non-descriptive exception: RuntimeError("populate() isn't reentrant")!Ultramontanism
I
11

It's definitely a circular import.

But i think is what you need is to use models as some sort of RetationFields(ForeignKey, ManyToManyField or OneToOneField) arguments. So you need to skip import and use as so:

# app1/models.py
class Model1(models.Model):
    relation_field = models.ForeignKey('app2.Model2')

From docs:

If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself

To refer to models defined in another application, you can explicitly specify a model with the full application label

Just put str object as first argument to relation fields that leeds to <app_name>.<Model_name>.

Note: it's better to avoid importing everything from module(from <module_name> import *)

Iorgos answered 8/5, 2017 at 12:11 Comment(0)
C
5

If you want to import only some specific module then do not use import *.

It will take more time load your all library and so can affect the speed of your app also.

If you want to use few modules from your second app then just add module name instead of whole libraries something like this:

from app2.models import Module1, Module2

or it may be circular import issue as other clarify.

Thanks.

Corny answered 8/5, 2017 at 12:11 Comment(1)
beautiful - this should be the accepted answerCarreon
N
3

i use this code always and it's work :)

from position_app.models import Member

Natica answered 8/5, 2017 at 13:11 Comment(0)
D
1

You need to specify the model names you want to import, for ex from app1.models import ModelName1, ModelName2.

Devin answered 8/5, 2017 at 12:7 Comment(0)
M
0

Make sure there is no name clash between one of your apps and one of the modules installed in your Python environment. If you use pip, you can run pip freezeto see a list of installed modules.

I had the same error when one of my apps was named 'packaging', and the packaging python module was installed.

Marine answered 8/6, 2018 at 12:45 Comment(0)
U
0

I also face this problem when I try to import my model from another app in (django2.2)

But at last I Imported It and Its successfully working.

here is my two app:

INSTALLED_APPS = [
    ...

    'categories',
    'videos',
]

and this is the code for how I Imported it into videos/models.py file as a ForeignKey Connectivity

from django.db import models

class Videos(models.Model):
    categories = models.ForeignKey('categories.Categories', related_name='categories', on_delete=models.CASCADE)

If want to see my Categories Model from categories/models.py file, you can check this code otherwise neglect it

from django.db import models

class Categories(models.Model): 
    category_name = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Uncap answered 25/5, 2019 at 23:0 Comment(0)
E
0

It is a circular import

In my case I needed the imported class not for a relation field, but for use it inside a method instead. If that's the case, I suggest to import inside the method, otherwise an AppRegistryNotReady("Models aren't loaded yet.") is raised.

class Student(CustomUser):
""" Usuario alumno """
class Meta:
    verbose_name = "Alumno"
    verbose_name_plural = "Alumnos"

def get_current_school_class(self):
    """ Obtiene el curso actual de un alumno """
    from school.models import SchoolClass, StudentClass
    # proceed with the method...
Exo answered 13/2, 2020 at 6:47 Comment(0)
B
0

it's not necessary to import models from others apps just put the app.models in the foreignkey field and that's work ;)

app 1:

class model1(models.Model):
    field=models.field type ...

app 2:

class model2(models.Model):
    field=models.ForeignKey('app1.model1', on_delete. ...)

to avoid code correction :D

Bonefish answered 22/10, 2020 at 12:10 Comment(1)
Welcome to SO! When you are about to answer an old question (this one is over 3 years old) that already has an accepted answer (that is the case here) please ask yourself: Do I really have a substantial improvement to offer? If not, consider refraining from answering.Lynellelynett

© 2022 - 2024 — McMap. All rights reserved.