1

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
  • Have you tried it with Widget's intake FK to-value as an string? Thus "your_app_label.Intake" – Blackeagle52 Dec 16 '20 at 23:32
  • why do you use ```"widgets.Widget"``` rather than ```"Widget"```? – ha-neul Dec 16 '20 at 23:34
  • @Blackeagle52 Do you mean to write `models.ForeignKey("intakes.Intake"...` instead of doing `models.ForeignKey(Intake...` –  Dec 16 '20 at 23:43
  • @ha-neul The reason for this is because these models are in different files, so if I were to import eachother, then I will get a circular import error. –  Dec 16 '20 at 23:48
  • I don't get that error with your models and the latest versions `Django==3.1.4` and `django-polymorphic==3.0.0`. When I run `makemigrations` Django creates three migrations `intake/migrations/0001_initial.py` (Create model Intake), `intake/migrations/0002_intake_start_widget.py` (Add field start_widget to intake), and `widgets/migrations/0001_initial.py` (Create model Widget). – Alasdair Dec 17 '20 at 15:37
  • I'm also a bit confused by your comment *having to comment out over and over again*. Even if you do get the circular dependency error you should only have to comment/uncomment once to create the initial migrations. – Alasdair Dec 17 '20 at 15:39
  • @Alasdair is there any way for you to share your code that you're doing right now in an answer? By commenting and unncommenting over and over I just meant whenever someone else needs to get set up. Thanks for your help!! –  Dec 18 '20 at 02:53
  • You would normally store the migrations in your version control system, so other users wouldn't have to run `makemigrations` to create the initial migrations. – Alasdair Dec 18 '20 at 09:46
  • There isn't really any code to share - I created a new project with two apps `intake` and `widgets`, and added the models to the `models.py`. The only change I had to make was to add imports for `PolymorphicModel` and `Intake`. – Alasdair Dec 18 '20 at 09:49

2 Answers2

2
     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:

  1. Delete all migrations.

  2. 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.

  1. run makemigrations

    python manage.py makemigrations

  2. get back your foreignkeys, replace all the following with blank

    models.CharField(('Disabled for Dependency issue'), max_length=20, blank=True) #

  3. run makemigrations again

    python manage.py makemigrations python manage.py migrate

1

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)
ha-neul
  • 3,058
  • 9
  • 24
  • I tried this (specifically "If you have to have two models in different models.py, then use name of models in both cases") but still didn't work :(. Let me know if I can provide any more info. Thanks for your time and help!! –  Dec 18 '20 at 02:55
  • That is odd, it works well in my case. In fact, in two models.py, one with "widgets.Widget" and the other ```Intake``` works too. I updated my answer with another way to do it. The only thing I did not try is to use ```PolymorphicModel```. But by using ```models.Model``` both ways work fine. So, if you are using string presentation, you should not import model from another app's models.py. – ha-neul Dec 18 '20 at 03:58
  • Did you delete migration files and try again? – ha-neul Dec 18 '20 at 03:59
  • Let me give it another shot and get back to you –  Dec 18 '20 at 04:09
  • Maybe you can paste full trace back. – ha-neul Dec 18 '20 at 05:45
  • It didnt work unfortunately.. I added the full error –  Dec 18 '20 at 06:16