Reputation:
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
Upvotes: 2
Views: 1376
Reputation: 11
This worked for me:
I ran
python manage.py makemigrations customers stores catalogue
and then
python manage.py migrate
that solved the problem of circular dependency between these three models
Upvotes: 1
Reputation: 1401
I'd just had a very similar CircularDependencyError
with Django 4.2.6.
My goal was to just get all our Django tests working in CI (after upgrading from an older Django) while rebuilding the DB every time like this:
rm -f data.sqlite.db && manage.py migrate && manage.py test
.
Neither passing a string as first argument to each ForeignKey
instead of a class, nor replacing (one, or the other, or both) the ForeignKey
's with dummy CharField
- none of that was resolving the error and I got pretty frustrated.
What ended up working was running manage.py makemigrations app1 app2
(with both apps simultaneously, instead of one by one).
As a result, Django generated not 1 but 2 migrations for one of the apps, and allowed me to run manage.py migrate
without CircularDependencyError
.
To be precise, I kept passing string as first argument to ForeignKey
, which might be necessary, but was definitely not sufficient in my case to resolve the error.
I think makemigrations
without parameters is supposed to go through the INSTALLED_APPS
and detect all missing migrations automatically, but it kept saying No changes detected
so I had to specify the apps myself, and made the mistake of doing it one by one.
Upvotes: 0
Reputation: 21
line 274, in ensure_not_cyclic
raise CircularDependencyError(", ".join("%s.%s" % n for n in cycle))
django.db.migrations.exceptions.CircularDependencyError: POS.0001_initial, CRM.0001_initial, CRM.0002_remove_divisions_cc
This type of errors that i approach for every fresh setup, the solution is quite simple:
Delete all migrations.
find all your "models.ForeignKey" in the project, replace them with:
models.CharField(('Disabled for Dependency issue'), max_length=20, blank=True) # models.ForeignKey
*Exclude environment directory.
run makemigrations
python manage.py makemigrations
get back your foreignkeys, replace all the following with blank
models.CharField(('Disabled for Dependency issue'), max_length=20, blank=True) #
run makemigrations again
python manage.py makemigrations python manage.py migrate
Upvotes: 2
Reputation: 3248
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)
Upvotes: 1