Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django/Python Circular model reference

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

like image 504
UserZer0 Avatar asked Jan 27 '11 06:01

UserZer0


People also ask

How do I avoid circular imports in Django?

Changing the name of the Working file different from the module which is imported in the script can avoid the Circular Imports problem. Import the module: Avoid importing objects or functions from a module that can cause Circular Imports. It is good to import the whole module to avoid the Circular Import.

What is circular dependency in Django?

Circular dependencies are imports in different Python modules from each other. You should never cross-import from the different models.py files, because that causes serious stability issues. Instead, if you have interdependencies, you should use the actions described in this recipe.

What causes circular import in Django?

Generally, the Python Circular Import problem occurs when you accidentally name your working file the same as the module name and those modules depend on each other. This way the python opens the same file which causes a circular loop and eventually throws an error.

How does Python handle circular import?

In simplest terms, a circular import occurs when module A tries to import and use an object from module B, while module B tries to import and use an object from module A. We'll run the code from run.py, which just imports a.py. As you can see, we get an exception as soon as b.py tries to import a.py.


1 Answers

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')
like image 95
Michael Dunn Avatar answered Oct 12 '22 22:10

Michael Dunn