Ошибка циклического импорта при попытке реализовать новый ForeignKey() в Django

Я работаю над проектом API, который предоставляет конечные точки для front-end. В связанную модель необходимо добавить новое поле "организация".

Во-первых, это поле должно быть добавлено в модель "File" как внешний ключ и другие связанные файлы, такие как populator, renderer и validator.

Во-вторых, фильтр 'organizationId' должен быть добавлен в конечную точку /files/.

Вот мои коды:

files/models.py

# Django
from django.db.models import(
        CharField,
        ForeignKey,
        PROTECT,
    ) 

# Authic - Common
from authic.common.models import Model

# Authic - Organization
from authic.organizations.models import Organization


ALLOWED_EXTENSIONS = [
    'avif', 'gif', 'jpeg', 'jpg', 'mp4', 'png', 'svg', 'webm', 'webp'
]


class File(Model):

    cloudinary_public_id = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=64
    )

    extension = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=4
    )
    
    organization = ForeignKey(
        Organization,
        on_delete=PROTECT,
        related_name='+',
        blank=True,
        null=True,
        default=None,
    )

    class Meta:
        db_table = 'files'

organizations/models.py

# Django
from django.db.models import (
    BooleanField,
    CharField,
    ForeignKey,
    PROTECT,
    TextField
)

# Authic - Common
from authic.common.models import Model

# Authic - Files
from authic.files.models import File


class Organization(Model):

    name = CharField(
        blank=False,
        null=False,
        default=None,
        max_length=256
    )
    url = CharField(
        blank=False,
        null=False,
        default=None,
        max_length=2048
    )
    theme_color = CharField(
        max_length=7,
        blank=False,
        null=False,
        default=None
    )
    logo = ForeignKey(
        File,
        on_delete=PROTECT,
        related_name='+',
        blank=True,
        null=True,
        default=None
    )
    html_title = CharField(
        blank=False,
        null=False,
        default=None,
        max_length=256
    )
    meta_image = ForeignKey(
        File,
        on_delete=PROTECT,
        related_name='+',
        blank=True,
        null=True,
        default=None
    )
    meta_description = TextField(
        blank=False,
        null=False,
        default=None
    )

    has_header_links = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_footer_links = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_footer_logo = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_filters = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_sorting = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_search = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    has_random_minting = BooleanField(
        blank=False,
        null=False,
        default=None
    )
    random_minting_preview_name = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=64
    )
    random_minting_preview_image_url = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=2048
    )
    token_id_strategy = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=64
    )
    twitter_handle = CharField(
        blank=False,
        null=False,
        default=None,
        max_length=64
    )
    custom_css = TextField(
        blank=True,
        null=True,
        default=None
    )
    has_custom_marketplace_header = BooleanField(
        blank=False,
        null=False,
        default=None
    )

    class Meta:
        db_table = 'organizations'

collections/models.py

Ошибка циклического импорта:

Прошу рассмотреть меня в качестве младшего разработчика программного обеспечения :D Спасибо!

Я внедрил поле organization в гораздо большее количество файлов, кроме "files". Я получаю ошибку циклического импорта, даже если пробовал обходные методы, такие как to="organizations.Organization" и т.д.

В случаях, подобных этому, вы можете использовать строку в точечной нотации для ссылки на модель внешнего ключа:

class MyModel(models.Model):
    foreign_key = models.ForeignKey(
        '<app name>.<model name>',
        on_delete=models.CASCADE,
    )

Например, поле logo вашей модели Organization можно записать следующим образом:

    logo = ForeignKey(
        "files.File",
        on_delete=PROTECT,
        related_name='+',
        blank=True,
        null=True,
        default=None
    )

То есть, имя приложения files, а имя модели File, поэтому у вас есть files.File.

В документации Django есть несколько хороших примеров: https://docs.djangoproject.com/en/4.1/ref/models/fields/#foreignkey

Я понял, что использование обходного метода to='.' работает, но я забыл удалить оператор импорта. После удаления ненужного оператора import все работает! Вот решение (files/models.py):

# Django
from django.db.models import(
        CharField,
        ForeignKey,
        PROTECT,
    ) 

# Authic - Common
from authic.common.models import Model

# Authic - Organization
#from authic.organizations.models import Organization --> unnecessary import


ALLOWED_EXTENSIONS = [
    'avif', 'gif', 'jpeg', 'jpg', 'mp4', 'png', 'svg', 'webm', 'webp'
]


class File(Model):

    cloudinary_public_id = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=64
    )

    extension = CharField(
        blank=True,
        null=True,
        default=None,
        max_length=4
    )
    
    organization = ForeignKey(
        to="organizations.Organization", # work around method(dot notation)
        on_delete=PROTECT,
        related_name='+',
        blank=True,
        null=True,
        default=None,
    )

    class Meta:
        db_table = 'files'
Вернуться на верх