2

I think this is more a python question than Django.

But basically I'm doing at Model A:

from myproject.modelb.models import ModelB

and at Model B:

from myproject.modela.models import ModelA

Result:

cannot import name ModelA

Am I doing something forbidden? Thanks

Constantin
  • 27,478
  • 10
  • 60
  • 79
Clash
  • 4,896
  • 11
  • 47
  • 67

2 Answers2

6

A Python module is imported by executing it top to bottom in a new namespace. When module A imports module B, the evaluation of A.py is paused until module B is loaded. When module B then imports module A, it gets the partly-initialized namespace of module A -- in your case, it lacks the ModelA class because the import of myproject.modelb.models happens before the definition of that class.

In Django you can fix this by referring to a model by name instead of by class object. So, instead of saying

from myproject.modela.models import ModelA
class ModelB:
    a = models.ForeignKey(ModelA)

you would use (without the import):

class ModelB:
    a = models.ForeignKey('ModelA')
Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • Thanks a lot Thomas! Saved my day! By the way, I think the syntax for `a = models.ForeignKey('ModelA')` is `models.ForeignKey('module.model')`, that's how it worked for me! – Clash Jan 22 '10 at 20:55
2

Mutual imports usually mean you've designed your models incorrectly.

When A depends on B, you should not have B also depending on A.

Break B into two parts.

B1 - depends on A.

B2 - does not depend on A.

A depends on B1. B1 depends on B2. Circularity removed.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Thanks for you answer! A person participates at max in one project, a project has only 1 leader. How do you remove the circularity from that? Person references a project. Project references it's leader (person) – Clash Jan 22 '10 at 20:56
  • @Clash: Many-to-many relationships do not require both sides to explicitly reference the other. You can do this in just one of the two. And. Why are they in separate modules? – S.Lott Jan 22 '10 at 21:17
  • S. Lott, it's not a many-to-many relationship, a person belongs to one project and a project has one leader – Clash Jan 22 '10 at 21:36
  • @Clash: Mutual relationships, like many-to-many, can be declared in just one place and will correctly reference the other. You do not need both to mutually include each other. **Why are they in separate modules?** – S.Lott Jan 22 '10 at 21:46
  • Oh, thank you S.Lott! That may be due because I missinterpreted the concept of modules... I thought project and person should be different modules, because they are different things – Clash Jan 22 '10 at 22:09
  • @Clash: Why did you think that? Can you provide a quote or a reference? – S.Lott Jan 24 '10 at 12:59
  • There is no quote or reference... it's because on Django tutorial, poll is separate module from the user, so I thought project would be a separate module from the user too – Clash Jan 25 '10 at 13:34
  • "B1 depends on A, A depends on B1" - that still looks like a circular reference to me. – Koterpillar Mar 15 '12 at 00:31
  • @Koterpillar: "A depends on B1. B1 depends on B2". That's the change that's required. You must make a change to eliminate the circularity. The change involves decomposition of *at least* one module into two. Sometimes both must be decomposed to eliminate the circularity. With a vague question it's hard to be specific in the answer. – S.Lott Mar 16 '12 at 01:57