61👍
If your dependency is with foreign keys referencing models in other applications, you don’t need to import the other model. You can use a string in your ForeignKey definition:
class MyModel(models.Model):
myfield = models.ForeignKey('myotherapp.MyOtherModel')
This way there’s no need to import MyOtherModel, so no circular reference. Django resolves the string internally, and it all works as expected.
5👍
I wrote the following a long time ago. Reading it now, it is not good advice for the OP’s question. They should probably just put their models into a single Django app. But the following is some general background on dependencies in code, and it mentions this "put them into one group" solution halfway through:
Ignoring the Django aspect to your question, the general technique for breaking circular dependencies is to break out one of the cross-referenced items into a new module. For example, the cycle:
moduleA: class1, class2
| ^
v |
moduleB: class3, class4
could become:
moduleB2: class4
|
v
moduleA: class1, class2
|
v
moduleB1: class3
Or alternatively, you could split up the classes from moduleA:
moduleA1: class1
|
v
moduleB: class3, class4
|
v
moduleA2: class2
Or both:
moduleA1: class1
|
v
moduleB1: class3
moduleB2: class4
|
v
moduleA2 class2
Of course, this is no help if class A & B depend on each other:
moduleA: class1
| ^
v |
moduleB: class2
In that case, maybe they should be in the same module (I suspect this is the solution the OP should use. Put the various interrelated model classes into a single Django app):
moduleA: class1 <---> class2
or maybe the classes can be broken down in some way. For example, perhaps a first step could be to break out the part of class1 that class2 needs, into a new class3, which both original classes depend upon:
moduleA: class1
| |
| v
moduleB: | class2
| |
v v
moduleC: class3(new!)
This has already broken the cycle. We might want to go one step further, and break out the part of class 2 that class 1 depends upon:
moduleA: class1
| |
| |
moduleB: | | class2
| | | |
| v v |
moduleC: | class3 |
| |
v v
moduleD: class4(new!)
Sometimes this kind of breakdown is difficult. Getting the hang of it is certainly a skill that requires some effort to learn. If it doesn’t go well, the resulting pieces seem very ad-hoc, specific to your problem, and you are left with a feeling that you have made your algorithm harder to understand by breaking it into multiple pieces. But when this process goes well, the resulting pieces feel like useful new primitives, which one could imagine being used elsewhere (even if that doesn’t actually happen in your current project), and using them makes your core algorithm easier to understand.
(Remember in the general case, that the above "dependency" arrows could represent any kind of dependency between the classes, which might be inheritance, or composition, etc. One class method might simply call a static method on another class. And when we talk of "classes", all of this applies equally to other chunks of logic, such as functions which depend on (i.e. call) each other, or database tables that reference each other.
- [Django]-I have a middleware where I a want to log every request/response. How can I access to POST data?
- [Django]-Models.py getting huge, what is the best way to break it up?
- [Django]-What is the best way to access stored procedures in Django's ORM
3👍
If you’re seeing circular model dependency I’m guessing that one of three things is happening:
- You’ve defined an inverse relationship to one that’s already defined (for instance both course has many lectures and lecture has one course) which is redundant in django
- You have a model method in the wrong app
- You’re providing functionality in a model method that ought to be in a manager
Maybe you could show us what’s happening in these models and we can try to figure out why the problem is arising. Circular model dependency is rarely an indication that you need to combine two apps – it’s more likely (though not definitely the case) that there’s a problem with one of your model definitions.
p.s. I am working on a similar django application, but my app structure is probably quite different to your’s. I’d be happy to give you a high-level description of it if you’re interested.
- [Django]-Do CSRF attacks apply to API's?
- [Django]-Any way to make {% extends '…' %} conditional? – Django
- [Django]-Exclude fields in Django admin for users other than superuser
2👍
Normally I advocate for splitting functionality into smaller apps, but a circular dependence between models reflects such a tight integration that you’re probably not gaining much from the split and might just consider merging the apps. If that results in an app that feels too large, there may be a way to make the split along a different axis, resulting in a more sane dependency graph.
- [Django]-Django query filter combining AND and OR with Q objects don't return the expected results
- [Django]-Django filter queryset __in for *every* item in list
- [Django]-Performing a getattr() style lookup in a django template