Столкнулся с проблемой циклического импорта

#python #django

Вопрос:

У меня есть два приложения (front и lrnadmin) в проекте (портал), это мой корневой каталог

введите описание изображения здесь

проблема в том, что когда я импортирую модели друг в друга, это выдает мне ошибку в этих моделях, я хочу квалификацию как внешний ключ, поэтому я хочу импортировать квалификацию из lrnadmin.models this is my front.models.py

 from datetime import datetime, timezone
from django.db import models
from django.db.models import expressions
from django.db.models.base import Model
from django.utils import timezone

from lrnadmin.models import Qualification

class Staff(models.Model):
    """Model definition for Staff."""
    # TODO: Define fields here
    nStaff = models.CharField(max_length= 50)
    role = models.CharField(max_length= 50)
    lrnQ = models.ForeignKey(Qualification, on_delete= models.CASCADE)
    relQ = models.CharField(max_length=200)
    relE = models.CharField(max_length=200)
    # Cv = models.CharField(max_length=100, blank=True, null=True)
    # Doc = models.CharField(max_length=100, blank=True, null=True)
    sec7 = models.ForeignKey(Sec7, on_delete=models.CASCADE)
    class Meta:
        """Meta definition for Staff."""

        verbose_name = 'Staff'
        verbose_name_plural = 'Staffs'

    # def __str__(self):
    #     """Unicode representation of Staff."""
    #     pass

 

и в этих моделях я хочу, чтобы User был внешним ключом, поэтому я хочу импортировать User из front.models
this is my lrnadmin.models.py

 from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils import timezone
from front.models import User

class CentreCode(models.Model):
    """Model definition for CentreCode."""

    # TODO: Define fields here
    user = models.ForeignKey(User, on_delete= models.CASCADE)
    centreCode = models.CharField(max_length= 20)
    categories = models.CharField(max_length = 20)
    authorisation = models.CharField(max_length= 20)
    registrationType = models.CharField(max_length= 20)

    class Meta:
        """Meta definition for CentreCode."""

        verbose_name = 'CentreCode'
        verbose_name_plural = 'CentreCodes'

    # def __str__(self):
    #     """Unicode representation of CentreCode."""
    #     pass
 

Как я могу справиться с этим

 File "E:lrnportallrnadminmodels.py", line 4, in <module>
    from front.models import User
  File "E:lrnportalfrontmodels.py", line 7, in <module>
    from lrnadmin.models import Qualification
ImportError: cannot import name 'Qualification' from partially initialized module 'lrnadmin.models' (most likely due to a circular import) (E:lrnportallrnadminmodels.py)
 

Комментарии:

1. Ошибка не может быть намного понятнее: «скорее всего, из-за циклического импорта». Если A импортирует B, а B импортирует A, как вы ожидаете, что это сработает?

2. итак, что мне делать.

3. Не импортируйте A из B, если вам нужно импортировать B из A, и наоборот. Либо импортируйте оба A и B из C и объедините их там, либо удалите один из импорта. (или поместите все в один и тот же модуль — если они так взаимозависимы, они все равно являются одним целым)

4. одним (грязным) обходным путем является задержка импорта A из B или наоборот. Например, если вы используете B внутри функции в A, добавьте local from B import ... в функцию, в которой используется импорт. Хотя следует отметить, что я бы предпочел предложить рефакторинг кода для решения проблемы импорта.

5. Мне нужна модель A в B и B в A. есть ли какое-либо решение

Ответ №1:

Вы можете «отложить загрузку» модели, используя строковый литерал, как описано в docs , так что, например, с моделью front приложения User вы можете определить ее следующим образом:

 # Remove from front.models import User


class CentreCode(models.Model):
    # ...
    user = models.ForeignKey('front.User', on_delete= models.CASCADE)
    # ...
 

Или, если вы определили front.models.User как пользовательскую пользовательскую модель, настоятельно рекомендуется просто ссылаться на пользовательскую модель, используя settings.AUTH_USER_MODEL , как описано here :

 from django.conf import settings
# Remove from front.models import User


class CentreCode(models.Model):
    # ...
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
    # ...
 

Комментарии:

1. мой пользователь — обычный класс моделей

2. пользователь класса (модели. Модель): «»»Определение модели для пользователя.»»» # ЗАДАЧА: определить поля здесь username = models . CharField(max_length= 50) пароль = модели. CharField(max_length = 200) категории = модели. CharField(max_length = 30) статус = модели. CharField(по умолчанию = «ожидающий», max_length = 20) роль = модели. CharField(по умолчанию =»центр», max_length= 20) created_date = модели. DateTimeField(по умолчанию = timezone.now)

3. Вы также указали это в настройках, используя AUTH_USER_MODEL ?

4. Я создал основную AUTH_USER_MODEL — это другая модель класса (Login)

5. В этом случае попробуйте использовать первый подход со строковым литералом. Хотя я должен сказать, что я не уверен, почему Login используется в качестве модели пользователя, но это зависит от вас

Ответ №2:

вы можете попробовать get_model, который позволит избежать импорта модели во время выполнения

    from django.apps import apps
   qualification_model = app.get_model('lrnadmin', 'Qualification')
 

или

вы можете попытаться импортировать модель внутри функции вместо импорта на уровне модуля