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)

К сожалению, я не знаю синтаксис наизусть, но вы можете понять, к чему я веду (надеюсь).

Надеюсь, это поможет, если у вас есть вопросы, пожалуйста, задавайте их :)

Вернуться на верх