django model- circular import problem

0

TIL

목록 보기
20/29
post-thumbnail

django로 프로젝트를 하다보면 내가 만든 앱들 사이를 넘나들며 작업을 하게 되는 경우가 많다. 이런 경우 import를 통해서 해당 모듈을 가져오게 되는데 이 과정에서 문제가 생긴 경험을 적어보려고 한다.

찜하기 기능!

웹사이트를 만들면서 찜하기 기능을 구현하고 싶었다. 찜하기 기능은 장바구니와는 또 다른 기능이라서 별도의 앱으로 구성을 하려고 했다.

우선 like라는 이름의 폴더를 만들고 그 폴더안에서 model을 구성했다.

찜하기의 필드 구성은 다음과 같다

  1. 찜하기를 한 날짜와 시간 -- 향후 데이터 분석적으로 유의미한 자료라 생각
  2. 찜하기를 한 사용자 -- 찜하기는 공유하는 것이 아닌 개인 정보
  3. 사용자가 찜한 상품 -- 진행하고 있는 사이트에 경우 요리재료!

like라는 테이블은 user와 ingredient의 M:M관계에서 중간테이블이다.

문제 발생

문제는 ingredient 테이블을 models.py를 통해서 정의를 해줄 때 발생했다.

ingredient파일을 정의해줄 때는 미리 m:m의 관계의 필드에 manytomany필드를 지정해주는 것이 좋다 (foreign 키로만 지정해도 무방하나 권장되지는 않음)

위 이미지에서 29번을 보면 알 수 있듯이 중간 테이블을 through = ~~이런 식으로 지정을 해준다. 그러면 여기서 문제가 발생을 한다!

Like라는 중간테이블은 분명 ingredient와 user 테이블을 참조한다.

그런데 필요한 ingredient테이블을 정의하는데 다시 Like 테이블이 필요한 상황이 발생한다.

필요한 테이블을 가져올려면 미리 import 과정을 거쳐야 하는데 정의되지 않은 파일을 중간에 가져올 수는 없기 때문에 circular import 에러가 발생하는 것이다.

이 상황은 장고의 특성 때문에 그러한데 필드값을 정의할 때 M:M의 중간테이블까지 지정을 해주어야 하다보니 미리 정의되기도 전에 import가 되는 것이다.

해결방법

이를 위해서는 두가지 해결방법이 있다

동일한 모델에서 작성

문제가 된 것은 위에 intertable을 import하는 과정에서 발생한 것이기 때문에 동일한 model에서 작성을 하게 되면 ingredient를 정의할 때 별도로 중간테이블을 import해줄 필요가 없다.


기존 찜하기와 유사하게 ingredient와 recipe의 m:m 관계의 중간테이블인 ingredientrecipe의 경우는 같은 ingredient.models에서 작성이 되었기 때문에 별도로 import할 필요가 없어서 순환참조 에러가 발생하지 않는다.
다만 기능적으로 분리를 할 필요가 있는 경우라면 이 해결방법은 부적합하다.

이름 지정해주기

스택오버플로우답변에서 알 수 있다시피 장고는 별도의 디렉토리에 있는 파일을 import없이도 지정을 해줄 수 있다.

방법은 해당app폴더.class명을 지정해주는 것인데 중요한 점은 str으로 만들어주어야 한다는 것이다.

이런 식으로 했을 때 제약이 없어지는 이유는 테이블을 만들 때 바로 만드는 것이 아니라 장고 중간관리자(?)에게 해당 텍스트가 전송이되고 그 텍스트를 기반으로 해당 클래스를 찾아서 연결해주는 단계가 있기 때문이라고 한다 ( 정확히 원리는 잘 모르겠으나 ... 여유가 생기면 추가로 공부해봐야겠다)

profile
기록을 통해 한 걸음씩 성장ing!

0개의 댓글