django INSTALLED_APPS에 잘못 기입으로 인한 import 오류

서재환·2022년 4월 14일
0

트러블슈팅

목록 보기
1/2

환경 설정

- 프로젝트 안에 가상환경을 만들지 않고 virtual env 가상환경을 사용

- cookiecutter 를 통한 프로젝트 구성

- 프로젝트 이름: wanted_pre_onboarding

사건 발단

테스트 코드를 작성한 후 아래 명령어로 테스트 코드를 실행했을 때 오류가 발생하였음

pytest wanted_pre_onboarding\posts\tests\test_views.py

오류 내용

\Python\Python310\lib\importlib\__init__.py", line 126, in import_module
  return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'posts'

posts 라는 app을 만들었는데 Module을 인식하지 못하는 문제 발생

import 담당하는 함수가 return은 해주어서 해당 함수를 살펴봄

def import_module(name, package=None):
    """Import a module.

    The 'package' argument is required when performing a relative import. It
    specifies the package to use as the anchor point from which to resolve the
    relative import to an absolute import.

    """
    level = 0
    if name.startswith('.'):
        if not package:
            msg = ("the 'package' argument is required to perform a relative "
                   "import for {!r}")
            raise TypeError(msg.format(name))
        for character in name:
            if character != '.':
                break
            level += 1
    return _bootstrap._gcd_import(name[level:], package, level)
내장 함수이므로 잘못된 함수일리가 없음 import의 상대적 경로로 작성한 부분을 절대적 경로로 
바꾸는 역할을 하는 함수인데 그 때 package 매개인자가 필요하다고 함. 테스트코드 작성한 파일
은 문제가 없었음 반환값까지 제대로 작동했는데 문제가 있는 걸 보면 해당 함수를 호출한 위 함수
를 살펴보기로 함
@classmethod
def create(cls, entry):
	"""
    Factory that creates an app config from an entry in INSTALLED_APPS.
    """
    # create() eventually returns app_config_class(app_name, app_module).
    app_config_class = None
    app_config_name = None 
    app_name = None
    app_module = None
			.
            .
            .
Appconfig 클래스 안의 클래스 메서드에서 import_module()함수를 호출하는 형태

해당 함수는 base.py에서 작성한 설정부문들 매개변수로 받는 함수임. 따라서 base.py에 작성한 설정
부문들을 보아야 할 필요가 있었음 base.py가 하는 역할은 config의 settings.py와 동일한 역할을
수행 다만 쿠키커터를 이용해 명칭이 다른 세팅파일일 뿐. 아래 디렉토리구조에서 base.py의 위치를 확
인할 수 있음

base.py 중 일부분 살펴보기

# APPS
# ------------------------------------------------------------------------------
DJANGO_APPS = [
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.sites",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # "django.contrib.humanize", # Handy template tags
    "django.contrib.admin",
    "django.forms",
    "wanted_pre_onboarding",
    "posts",
]
THIRD_PARTY_APPS = [
    "crispy_forms",
    "crispy_bootstrap5",
    "allauth",
    "allauth.account",
    "allauth.socialaccount",
]

LOCAL_APPS = [
    "wanted_pre_onboarding.users",
    # Your stuff: custom apps go here

]
import_module 함수를 호출한 create() '클래스메서드'의 경우

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS 를 의미함, 즉 list의 합인데
해당 부문에서 인자로는 잘 들어갔지만 잘못 기입하여 그 역할을 하지 못한 부분이 생겼다는 의미

쿠키커터로 기본 설정을 해준 이후 내가 설정한 부문은 DJANGO_APPS와 LOCAL_APPS 부문이고 posts 모
듈을 임포트할 수 없다고 하였기 때문에 'posts'를 'wanted_pre_onboarding.posts'로 변경함

그리고 다시  pytest wanted_pre_onboarding\posts\tests\test_views.py 유닛테스트를 실시하였더
니 버그가 잡힘

정리 및 결론

설정부문에 적을 때 wanted_pre_onboarding이라는 폴더 안의 앱이름도 wanted_pre_onboarding
으로 설정하다보니 해당 프로젝트안에 posts라는 앱이 있는 구조를 간과하고 posts라 적게되었음.

INSTALLED_APP안의 문자열을 인식하는 기준이 폴더이름이 있는 위치를 기준으로 앱의 위치를 적어주어야 
하는 부문을 알게됨

하아... 이런 쓰잘데기 없는 걸 찾은 것이 개발 인생에 도움이 될지는 모르겠지만 구글링 해서 안나온 버
그를 스스로 해결했다는 부문에 의의를 두기로 했음. 이런 버그가 없는 걸 보면 잘 마주하는 버그도 아니
겠지만서도

posts.app.py

from django.apps import AppConfig

class PostsConfig(AppConfig):
    name = 'wanted_pre_onboarding.posts'
posts앱의 app.py PostsConfig 클래스의 name도 위와 같이 설정해 주어야함.

디렉토리구조 (참고)

wanted_pre_onboarding
├─ .git
├─ .gitattributes
├─ .gitignore
├─ config
│  ├─ settings
│  │  ├─ base.py
│  │  ├─ local.py
│  │  ├─ production.py
│  │  ├─ test.py
│  │  └─ __init__.py
│  ├─ urls.py
│  ├─ wsgi.py
│  └─ __init__.py
├─ locale
│  └─ README.rst
├─ manage.py
├─ pytest.ini
├─ README.md
├─ requirements
│  ├─ base.txt
│  ├─ local.txt
│  └─ production.txt
├─ setup.cfg
├─ utility
└─ wanted_pre_onboarding
   ├─ conftest.py
   ├─ contrib
   │  └─ __init__.py
   ├─ posts
   │  ├─ admin.py
   │  ├─ apps.py
   │  ├─ migrations
   │  │  ├─ 0001_initial.py
   │  │  └─ __init__.py
   │  ├─ models.py
   │  ├─ tests
   │  │  ├─ test_views.py
   │  │  └─ __init__.py
   │  ├─ tests.py
   │  ├─ urls.py
   │  ├─ views.py
   │  └─ __init__.py
   ├─ static
   │  ├─ css
   │  │  ├─ posts
   │  │  │  ├─ base.css
   │  │  │  └─ header.css
   │  │  └─ project.css
   │  ├─ fonts
   │  │  └─ .gitkeep
   │  ├─ images
   │  │  └─ favicons
   │  │     └─ favicon.ico
   │  └─ js
   │     └─ project.js
   ├─ templates
   │  ├─ posts
   │  │  ├─ base.html
   │  │  ├─ header.html
   │  │  ├─ index.html
   │  │  └─ product_create.html
   │  └─ users
   │     ├─ main.html
   │     ├─ user_detail.html
   │     └─ user_form.html
   ├─ users
   │  ├─ adapters.py
   │  ├─ admin.py
   │  ├─ apps.py
   │  ├─ context_processors.py
   │  ├─ forms.py
   │  ├─ migrations
   │  │  ├─ 0001_initial.py
   │  │  ├─ 0002_auto_20220413_1536.py
   │  │  └─ __init__.py
   │  ├─ models.py
   │  ├─ urls.py
   │  ├─ views.py
   │  └─ __init__.py
   ├─ utils
   │  ├─ storages.py
   │  └─ __init__.py
   └─ __init__.py

0개의 댓글