CircularDependencyError on Foreign Keys Pointing to Each Other Django
I get a circular dependency error that makes me have to comment out a field. Here is how my models are set up:
class Intake(models.Model):
# This field causes a bug on makemigrations. It must be commented when first
# running makemigrations and migrate. Then, uncommented and run makemigrations and
# migrate again.
start_widget = models.ForeignKey(
"widgets.Widget",
on_delete=models.CASCADE,
related_name="start_widget",
null=True,
blank=True,
)
class Widget(PolymorphicModel):
intake = models.ForeignKey(Intake, on_delete=models.CASCADE)
By the way, Widget's PolymorphicModel superclass is from here. Why is this happening and how can I solve it without having to comment out over and over again? Thanks!
EDIT: THE FULL ERR:
Traceback (most recent call last):
File "/Users/nicksmith/Desktop/proj/backend/manage.py", line 22, in <module>
main()
File "/Users/nicksmith/Desktop/proj/backend/manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/base.py", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/base.py", line 371, in execute
output = self.handle(*args, **options)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/base.py", line 85, in wrapped
res = handle_func(*args, **kwargs)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 92, in handle
executor = MigrationExecutor(connection, self.migration_progress_callback)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/db/migrations/executor.py", line 18, in __init__
self.loader = MigrationLoader(self.connection)
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/db/migrations/loader.py", line 53, in __init__
self.build_graph()
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/db/migrations/loader.py", line 282, in build_graph
self.graph.ensure_not_cyclic()
File "/Users/nicksmith/Desktop/proj/backend/venv/lib/python3.9/site-packages/django/db/migrations/graph.py", line 274, in ensure_not_cyclic
raise CircularDependencyError(", ".join("%s.%s" % n for n in cycle))
django.db.migrations.exceptions.CircularDependencyError: intakes.0001_initial, widgets.0001_initial
In Django doc about foreignkey:
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:
Here is an example from the doc:
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
So, in your case, this might work:
# put both models in the same models.py
class Intake(models.Model):
start_widget = models.ForeignKey(
"Widget", # use "Widget" the name of the model
on_delete=models.CASCADE,
related_name="start_widget",
null=True,
blank=True,
)
class Widget(PolymorphicModel):
intake = models.ForeignKey(Intake, on_delete=models.CASCADE)
Or
class Widget(PolymorphicModel):
intake = models.ForeignKey("Intake", on_delete=models.CASCADE) #use "Intake" rather than Intake.
class Intake(models.Model):
start_widget = models.ForeignKey(
Widget,
on_delete=models.CASCADE,
related_name="start_widget",
null=True,
blank=True,
)
If you have to have two models in different models.py, then use name of models in both cases.
# they are in separate models.py
##### in this case, do not import models from the other app.
class Widget(PolymorphicModel):
intake = models.ForeignKey("myapp.Intake", on_delete=models.CASCADE)
#use "myapp.Intake" rather than Intake.
# in different models.py
# use "widgets.Widget" rather than Widget
class Intake(models.Model):
start_widget = models.ForeignKey(
"widgets.Widget",
on_delete=models.CASCADE,
related_name="start_widget",
null=True,
blank=True,
)
Or import model from one app, but use "myapp.MyModel" in the other app.
# in this models.py, do not import Widget model
class Intake(models.Model):
start_widget = models.ForeignKey(
"widgets.Widget",
on_delete=models.CASCADE,
related_name="start_widget",
null=True,
blank=True,
)
#### in another models. py
from myapp.models import Intake # import model
class Widget(PolymorphicModel):
intake = models.ForeignKey(Intake, on_delete=models.CASCADE)