Python – Django/Python Circular model reference

djangodjango-modelspython

Ok So I'm TRYING to write nice organized code and actually making seperate django apps instead of lumping everything together into 1. My problem is that I have 3 apps that each reference 1 other model from the next app. So basically I have an endless loop, App A needs to know about B.models.something1 , App B needs to know about C.models.Somthing2, and App C needs to know about A.models.something3 . This of course will not run, for those wondering if this is actually a problem 🙂 .Is there anything resembling a predeclaration of classes so python will know that the classes actually exist?

Thanks.

EDIT: More Code:
Unfortunatly the nature and models of my project are confidential so I'll have to change the names to reflect something completely different , but the code will remain the same.

teacher/models.py

 from django.db import models
 from myapp.student.models import *
 from django.contrib.auth.models import User
 class Teacher(models.Model):
     """(description)"""
     user = models.ForeignKey(User)
     name = models.CharField(max_length=100)
     phone = models.CharField(max_length=13)
     phone_ext = models.CharField(blank=True, max_length=5)
     fax = models.CharField(blank=True, max_length=13)
     fax_ext = models.CharField(blank=True, max_length=100)
     url = models.URLField(blank=True, verify_exists=True)
     complaint = models.ManyToManyField(Complaint)
     city = models.CharField(blank=True, max_length=100)
     state = models.CharField(blank=True, max_length=100)
     postal_code = models.CharField(blank=True, max_length=15)
     location = models.ManyToManyField(Location)
     def __unicode__(self):
         return self.name
 class Location(models.Model):
     """(description)"""
     city = models.CharField(blank=True, max_length=100)
     state = models.CharField(blank=True, max_length=100)
     country = models.CharField(blank=False, max_length=100)
     def __unicode__(self):
         return self.city + ", " + self.state +", "+self.country

student/models.py

 from django.db import models
 from django.contrib.auth.models import User
 from myapp.school.models import School

 class Student(models.Model):
     """(Student description)"""
     user = models.ForeignKey(User)
     country = models.CharField(max_length=100)
     state = models.CharField(max_length=100)
     city = models.CharField(max_length=100)
     locale = models.CharField(blank=False, max_length=5)
     learningtype = models.CharField(blank=True, max_length=100)
     sites = models.TextField(blank=True)
     def __unicode__(self):
         return str(self.user)

 class Complaint(models.Model):
     """(Complaint description)"""
     student = models.ForeignKey(Student)
     site = models.ForeignKey(School)
     complaint = models.TextField(blank=False)
     def __unicode__(self):
         return str(self.site)

school/models.py

 from django.db import models
 from myapp.teacher.models import Location
 class School(models.Model):
     """(School description)"""
     name = models.CharField(max_length=100)
     url = models.URLField(verify_exists=True)
     img = models.ImageField(upload_to="casion_img/")
     rating = models.FloatField()
     description = models.CharField(blank=True, max_length=300)
     goodstanding = models.BooleanField(default=True)
     location = models.ForeignKey(Location)
     def __unicode__(self):
         return self.name

So here's what I'm getting:

File "/Users/userzero/django/myapp/school/models.py", line 2, in
from teacher.models import Location
File "/Users/userzero/django/myapp/teacher/models.py", line 2, in
from student.models import Complaint
File "/Users/userzero/django/myapp/student/models.py", line 3, in
from school.models import School
File "/Users/userzero/django/myapp/casino/models.py", line 2, in
from teacher.models import Location
ImportError: cannot import name Location

Best Answer

From the docs:

To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you'd need to use:

class Car(models.Model):
     manufacturer = models.ForeignKey('production.Manufacturer')

This sort of reference can be useful when resolving circular import dependencies between two applications.

So for your apps, try changing e.g.

 location = models.ForeignKey(Location) 

to

 location = models.ForeignKey('Location')

Note that if this model is in a different app then you need to specify that too (thanks @Bran for pointing this out), e.g.

 location = models.ForeignKey('teacher.Location')