【问题标题】:Django models - Circular-Import-IssueDjango 模型 - 循环导入问题
【发布时间】:2020-07-11 00:59:45
【问题描述】:

我的 Django 项目使用三个应用程序,chat, user, sowi。每个应用程序都具有以下结构的模型。启动服务器时出现错误,我认为这是因为我有循环导入。我该如何解决这个问题?

聊天/models.py

from user.models import User

class Chat(models.Model):
    name = models.CharField(max_length=100, default="private")


class Message(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE)
    receiver = models.ForeignKey(Chat, on_delete=models.CASCADE)

user/models.py

from chat.models import Chat
from sowi.models import Sowi

class User(AbstractUser):
    chats = models.ManyToManyField(Chat, blank=True)
    subscriptions = models.ManyToManyField(Sowi, related_name="subscriptions", blank=True)
    memberships = models.ManyToManyField(Sowi, related_name="memberships", blank=True)
    blocked = models.ManyToManyField("self", related_name="blocked", blank=True)

sowi/models.py

from chat.models import Chat, Message
from user.models import User

class Sowi(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    chat = models.OneToOneField(Chat, blank=True, null=True, on_delete=models.CASCADE)

错误信息

File "*/sowi/models.py", line 9, in <module>
    from chat.models import Chat, Message
  File "*/chat/models.py", line 4, in <module>
    from user.models import User
  File "*/user/models.py", line 5, in <module>
    from chat.models import Chat
ImportError: cannot import name 'Chat' from 'chat.models'

提前致谢!

【问题讨论】:

  • 如果您提供更多背景信息会有所帮助。您甚至没有在示例代码中的错误中表示该行。
  • @eatmeimadanish 你说得对,我加了它

标签: python django python-3.x sqlite django-models


【解决方案1】:

最好用字符串字面量来引用模型,而不是用模型类来引用它。 Django 可以处理并自动解决这些问题:

# chat/models.py

from django.db import models

class Chat(models.Model):
    name = models.CharField(max_length=100, default="private")

class Message(models.Model):
    sender = models.ForeignKey('user.User', on_delete=models.CASCADE)
    receiver = models.ForeignKey(Chat, on_delete=models.CASCADE)

# user/models.py

from django.db import models

class User(AbstractUser):
    chats = models.ManyToManyField(Chat, blank=True)
    subscriptions = models.ManyToManyField('sowi.Sowi', related_name="subscriptions", blank=True)
    memberships = models.ManyToManyField('sowi.Sowi', related_name="memberships", blank=True)
    blocked = models.ManyToManyField("self", related_name="blocked", blank=True)

# sowi/models.py

from django.db import models

class Sowi(models.Model):
    owner = models.ForeignKey('user.User', on_delete=models.CASCADE)
    chat = models.OneToOneField('chat.Chat', blank=True, null=True, on_delete=models.CASCADE)

最好reference the user model [Django-doc]设置AUTH_USER_MODEL setting [Django-doc],并使用这个设置,这样如果你以后改变主意,你可以更方便地改变这个:

# chat/models.py

from django.conf import settings
from django.db import models

class Chat(models.Model):
    name = models.CharField(max_length=100, default="private")

class Message(models.Model):
    sender = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    receiver = models.ForeignKey(Chat, on_delete=models.CASCADE)

# user/models.py

from django.db import models

class User(AbstractUser):
    chats = models.ManyToManyField(Chat, blank=True)
    subscriptions = models.ManyToManyField('sowi.Sowi', related_name="subscriptions", blank=True)
    memberships = models.ManyToManyField('sowi.Sowi', related_name="memberships", blank=True)
    blocked = models.ManyToManyField("self", related_name="blocked", blank=True)

# sowi/models.py

from django.conf import settings
from django.db import models

class Sowi(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    chat = models.OneToOneField('chat.Chat'

【讨论】:

  • 谢谢,它就像一个魅力。再一次,你救了我的**。跟上很棒的帮助!
  • 为我节省了很多时间。谢谢
【解决方案2】:

尝试:

class User(AbstractUser):
    chats = models.ManyToManyField('chat.Chat', blank=True)
    subscriptions = models.ManyToManyField('sowi.Sowi', related_name="subscriptions", blank=True)
    memberships = models.ManyToManyField('sowi.Sowi', related_name="memberships", blank=True)
    blocked = models.ManyToManyField("self", related_name="blocked", blank=True)

您的代码的问题是您在用户models.py 中导入ChatSowi,然后您尝试在ChatSowi 中导入用户models。你看到那里的循环导入了吗?

【讨论】: