Django simple app вызывает ошибку циклического импорта, за которой следует ошибка определения
У меня возникла, казалось бы, простая ошибка определения, при которой класс Automation
не определен. Я создал очень простое приложение под названием automations
, которое, похоже, вызвало проблему, несмотря на то, что его практически не меняли. Обратите внимание, что есть также другое приложение под названием messages
, имеющее отношения многие:многие с новыми автоматизациями.
Автоматизация - это просто приложение с этим простым файлом models.py:
from django.db import models
from accounts.models import Account
from messages.models import Message
class Automation(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
messages = models.ManyToManyField(Message)
def __str__(self):
return self.name
А сообщения - это отдельное приложение с этим файлом models.py:
from django.db import models
from accounts.models import Account
# from automations.models import Automation # < FAILS
from automations.models import * # < WORKS
# from apps.get_model(email_messages, Message) # < FAILS
# from django.apps get_model(email_messages, Message) # < FAILS
# from django.apps import apps # < FAILS
# Automations = apps.get_model('email_messages', 'Messages') # < FAILS
class Message(models.Model):
name = models.CharField(max_length=100)
subject = models.CharField(max_length=128)
text = models.TextField()
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
automations = models.ManyToManyField(Automation) # < PROBLEMATIC LINE
def __str__(self):
return self.name
Изначально у меня был такой импорт from automations.models import Automation
, который вызвал эту ошибку:
ImportError: cannot import name 'Automation' from partially initialized module 'automations.models' (most likely due to a circular import)
Но я больше не получал эту ошибку после добавления from automations.models import *
. Однако теперь я получаю ошибку определения NameError: name 'Automation' is not defined
при добавлении automations = models.ManyToManyField(Automation)
к классу Message
.
Кто-нибудь знает, почему это происходит? Я просто хочу добавить отношение многие:многие между классами Message
& Automation
(предположительно, поле ManytoManyField(Class)
нужно добавить в оба класса?).
Я прочитал другие сообщения с подобными проблемами, но не смог найти решения. Спасибо
Предупреждение!
Я не профессионал и говорю только на основе небольшого опыта. Возможно, есть нормальное решение, но я его пока не нашел!
Я наткнулся на этот тип ошибки, и причина ее очень проста. Причина, по которой вы не можете этого сделать, заключается в том, что в таких случаях нужно быть конкретным. Например, чтобы лучше представить себе перспективу, представьте, как будут выглядеть классы, когда вы хотите смоделировать семью.
Вы можете подумать о чем-то вроде:
Mother, Father -> Child
Child -> Mother, Father
Проблема в том, что это невозможно, поскольку один из них должен быть создан раньше другого. Именно по этой причине вы получаете ошибку циклического типа.
Обычно вы могли бы создать это, но с точки зрения компьютера, ему нужно знать, сколько памяти он должен выделить для объекта, а поскольку объекты хотят быть друг в друге, вы получите что-то вроде этого (теоретически):
Allocate -> mother(childe(mother(child(....)), father(child(....))))
что, я надеюсь, вы видите, будет бесконечным циклом выделения бесконечности.
Чтобы быть еще более конкретным, python делает здесь то, что он пытается "скопировать-вставить" все, что вам нужно, прямо там, где вы это объявили. Так что здесь происходит то, что вы сказали ему в файле B -> import A
, а в A
вы сказали import B
, что означает, чтобы заставить его работать, в конце, он должен "скопировать-вставить" себя на место импорта (так B -> import A -> import B => B -> imports B => impossible
)
Единственное решение, которое, по крайней мере, я смог найти, было примерно таким: https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/ (Ознакомьтесь с тем, как он смоделирован)
Единственный способ получить доступ к другому объекту (допустим, у вас есть публикация, и вы хотите узнать, в каких статьях она есть в поле M2M) - это перебрать все статьи, когда вы хотите узнать, в каких статьях есть публикация.
Переходим ко второй части вопроса. Почему при использовании import *
не вылетает круговая ошибка. Я лично думаю, что причина в том, что python - интерпретируемый язык, и он делает много ленивой загрузки. Я имею в виду, что он знает, когда видит import A -> import B -> import A
, но когда вы вводите *
, проверка синтаксиса не замечает этого, пока не дойдет до конкретной строки. Подобные ошибки можно увидеть, когда вы используете неправильное имя метода в классе, и python замечает это после того, как пытается вызвать упомянутый метод.
Я не очень уверен во втором ответе, но я вижу, что это очень часто происходит, когда я неправильно ввожу имя функции
.
Другими словами, что вам нужно сделать: Удалите один из импортов, чтобы устранить проблему кругового импорта (выберите один, который больше подходит, как в примере с семьей, который я упомянул (должно быть более ясно, какой из них должен искать другой)))
Доступ к другой части M2M (в PSEUDOCODE !!!!):
Article.objects.filter(publication in publications)
К сожалению, я не знаю синтаксис наизусть, но вы можете понять, к чему я веду (надеюсь).
Надеюсь, это поможет, если у вас есть вопросы, пожалуйста, задавайте их :)