相互指向Django的外键上的CircularDependencyError [英] CircularDependencyError on Foreign Keys Pointing to Each Other Django

查看:39
本文介绍了相互指向Django的外键上的CircularDependencyError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到一个循环依赖错误,这使我不得不注释掉一个字段.这是我的模型的设置方式:

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)

顺便说一句,Widget的PolymorphicModel超类来自此处.为什么会发生这种情况,我该如何不必反复评论来解决?谢谢!

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!

完整错误:

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

推荐答案

在Django文档中关于外键:

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)

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,
    )

如果必须在不同的模型中有两个模型.py,则在两种情况下都使用模型名称.

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,
    )

或从一个应用程序导入模型,但使用"myapp.MyModel"在另一个应用程序中.

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)

这篇关于相互指向Django的外键上的CircularDependencyError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆