[Django] Django circular import 문제

Youngshin Park·2024년 9월 19일
1

Django

목록 보기
1/3
post-thumbnail

오랜만에 벨로그를 쓰려 한다 ..
왜냐? 개발이 오랜만이니까 ..

내가 요즘 drf 백엔드 개발 중인데 처음 써보는 것들이 많다. 그래서 매우 설레면서도 .. 역시 배움에는 끝이 없다는 것을 느끼기도 한다.

이번에 celery랑 redis를 첨 쓰면서 tasks.py 파일을 생성하였고 models.py 서로 임포트를 할 일이 있었는데 여기서 생긴 오류에 대해 설명해보려 한다.

추후 .. celery와 redis 관련 게시물도 정리해보려 한다 !!


코드

우선 하나의 앱 내에서 models.py와 tasks.py 를 서로 import 하면서 발생한 문제니까 문제 발생 때의 코드를 보여주겠다.

models.py

from django.db import models
from django.utils import timezone
from booth.models import Booth
from .tasks import check_confirmed, check_ready_to_confirm

class Waiting(models.Model):

위와 같이 models.py에서 같은 앱 내의 'tasks.py' 내 함수들을 import 한 상태였다.

tasks.py

from celery import shared_task
from django.utils import timezone
from .models import Waiting

@shared_task
def check_ready_to_confirm(waiting_id):


@shared_task
def check_confirmed(waiting_id):

tasks.py는 위와 같이 작성되어 있었다. 함수 내 코드는 굳이 쓰지 않겠다. 상단에 같은 앱 내의 models.py 내 모델을 import 해 오던 것이다.

이때 나는 룰루랄라 다 작성한 줄 알고 API 테스트를 하기 위해
python manage.py makemigrations
명령어를 실행했는데 ...!!!

문제

빠밤사진과 같은 오류가 난 것이다...

File "/Users/dudtlstm/Desktop/LINENOW-Server/waiting/models.py", line 4, in
from .tasks import check_confirmed, check_ready_to_confirm
File "/Users/dudtlstm/Desktop/LINENOW-Server/waiting/tasks.py", line 3, in
from .models import Waiting
ImportError: cannot import name 'Waiting' from partially initialized module 'waiting.models' (most likely due to a circular import) (/Users/dudtlstm/Desktop/LINENOW-Server/waiting/models.py)

흠.. 뭐가 문제일까 두 파일을 번갈아가면서 엄청 열심히 찾아봤다..
1. 오타
2. 이외의 문제 ..

열심히 찾아봐도 답이 안 나오길래 내 칭구 GPT 선생을 불렀다 !!!!


해결책

!!!! models.py에서 tasks.py를 tasks.py에서 models.py를 !! 서로 호출하니 '순환 호출'이 되는 것이었다.

순환 참조 문제는 Python에서 두 모듈이 서로를 참조할 때 발생하는 일반적인 문제입니다.

그렇다고 한다 ... 쩝 그동안 이걸 전혀 몰랐다니. 바보 아닌가? 이제라도 알았으니 됐다.

제시해준 해결책은 아래와 같다.

from celery import shared_task
from django.utils import timezone

@shared_task
def check_ready_to_confirm(waiting_id):
  """3분 후 ready_to_confirm 상태에서 입장 확정되지 않았으면 취소"""
  from .models import Waiting


@shared_task
def check_confirmed(waiting_id):
  """10분 후 입장 확정 상태에서 도착하지 않으면 취소"""
  from .models import Waiting

이런 식으로 각 함수 내에서 필요할 때 호출하는 것 !!!

위와 같이 고치니 마이그레이션이 잘 되긴 하나 ..

개인적으로 뭔가 항상 임포트하는 건 맨위에 써서 그런가 함수 내에 쓰는 게 익숙하지가 않고 맞는 방법인지 잘 모르겠다..!

또 다른 좋은 해결책을 찾으면 다시 기술하도록 하겠다.

우리 ㄹㅇㄴㅇ 파이팅 !!!!!

재밌는 개발 중입니댜 다들 기대해주세요
그리고 오랜만의 배움의 즐거움을 느껴서 기부니가 죠음 💗

그럼 모두

개발팅🐱

0개의 댓글