환경 설정
- 프로젝트 안에 가상환경을 만들지 않고 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.
"""
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 중 일부분 살펴보기
DJANGO_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.staticfiles",
"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",
]
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