Skip to content

django

3 posts with the tag “django”

장고(Django) 환경의 Jupyter Notebook 실행하기

Django로 웹개발을 하다보면 Django의 ORM(Object-relational Mapping)을 자주 사용하게 됩니다. Django의 ORM 관련 문서는 여기를 참고해 주세요.

from django.db import models 모듈의 Model 클래스로 DB를 쉽게 구축할 수 있습니다. 그럼에도 DB 구축 과정에서 테스트성 작업도 필요하게 됩니다. 예를들어, 테스트 데이터를 생성해 보거나, 모델을 이용하여 질의(Query)를 만들어 보거나, 데이터를 수정해 보거나, 테스트로 입력한 데이터들을 삭제하거나 등입니다. 즉, 데이터 CRUD(Create, Retrieve, Update, Delete)를 테스트 해볼일이 많습니다.

Django 설정이 로딩된 상태에서만 모델들을 사용할 수 있습니다. 이들을 테스트하기 위해서 Django View에서 테스트 코드를 작성하고 GET 호출을 하는 번거롭고 비효율적인 방법으로 테스트할 수도 있습니다만, 보다 효과적인 방법을 소개합니다.

Terminal window
python manage.py shell

이렇게 Django 프로젝트의 설정이 로딩된 쉘을 실행하고, 이 위에서 모델들을 다룰 수 있습니다.

먼저 django-extensions를 설치합니다.

Terminal window
pip install django-extensions

그리고 settings.py에서 INSTALLED_APPS 리스트에 django_extensions를 추가합니다.

INSTALLED_APPS = [
...
'django_extensions',
]

이제 다음과 같이 shell_plus를 실행하면 관련있는 Django 모듈들을 자동으로 임포트해 줍니다.

Terminal window
python manage.py shell_plus

3. django-extensions의 shell_plus + Jupyter Notebook

Section titled “3. django-extensions의 shell_plus + Jupyter Notebook”

Django 환경을 Jupyter Notebook(Lab)으로 사용할 수 있습니다.

Terminal window
python manage.py shell_plus --notebook

Django 서버 시작할 때 실행할 코드 설정하기

Django는 파이썬 계열에서 대표적인 웹 프레임워크 입니다. 많지는 않지만 서버를 실행함과 동시에 특정 코드를 실행할 일이 생깁니다. 예를 들어서, 서버를 시작하면서 파일을 읽거나, 객체를 생성해 놓거나, 다른 서버에 메시지를 전송하는 등이 될 수 있습니다.

이 때, AppConfig를 사용하면 됩니다. 먼저 AppConfig를 상속하는 클래스를 정의합니다.

app/broker.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
verbose_name = "My App"
def ready(self):
# TODO: Write your codes to run on startup
pass

이렇게 정의한 클래스를 __init__.py에 명시해 주면 끝입니다.

app/__init__.py
default_app_config = 'app.broker.MyAppConfig'

그런데 한가지 주의할 점이 있습니다. 이 부분을 간과하면 곤란한 상황이 생길 수 있습니다. Django가 기본적으로 코드 검증 과정에서 한번, 코드 실행 과정에서 한번, 총 2번 MyAppConfig를 실행합니다.

두번 실행되는 일을 피하기 위해서 Django 서버를 실행할 때 다음과 같이 --noreload 옵션을 넣어줍니다.

Terminal window
python manage.py runserver 0.0.0.0:8000 --noreload

Django에서 Jinja2를 Template Engine으로 사용하기

Django는 대표적인 Python 웹 프레임워크 입니다. 페이지 렌더링, ORM, Session 자체 Template Engine도 가지고 있지요.

그런데 개인적인 의견으로 Template Engine은 Jinja2가 더 강력한 것 같습니다. 다행히 Django에서 Jinja2도 지원을 하고 있습니다. 다만 약간의 추가적인 세팅이 필요하죠.

이 포스트에서 Django에서 Jinja2를 사용하는 방법을 차근차근 설명하고자 합니다.

우선 Jinja2를 설치합니다.

Terminal window
$ pip install Jinja2

Django 프로젝트의 settings.py 파일을 수정합니다.

TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
'app/templates'
],
'APP_DIRS': True,
'OPTIONS': {
'extensions': [
'jinja2.ext.do',
'jinja2.ext.loopcontrols',
'jdj_tags.extensions.DjangoCompat',
],
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

여기서 Jinja2 부분의 OPTION/extensions에 Jinja2에서 기본 제공하는 확장 기능들을 추가할 수 있습니다. jinja2.ext.dojinja2.ext.loopcontrols는 Jinja2의 기본 확장 기능입니다. Jinja2 Extensions에서 다른 확장 기능들도 확인해 보세요. jdj_tags.extensions.DjangoCompat는 Django Template Engine이 제공하는 Template Tag들을 Jinja2 버전으로 만들어 놓은 커스텀 확장 기능입니다. 이걸 사용하기 위해서 pip install jinja2-django-tags로 모듈을 설치합니다.

이렇게 하면 이제 Jinja2를 Template Engine으로 사용하게 됩니다. 그런데 Jinja2에서는 Custom Filter를 기존 Django 방식으로 할 수 없습니다.

필터 함수들을 가지고 있는 모듈 filters.py를 다음과 같이 정의합니다.

""" filters.py
"""
from django.utils.http import urlquote
# collection
def filter_getitem(value, arg):
return value.get(arg, '')
def filter_getat(value, arg):
try:
return value[int(arg)]
except Exception as e:
return None
def filter_notinappend(a, b):
if b not in a:
a.append(b)
return a
def filter_union(a, b):
return set(a) | set(b)
# math
def filter_divide(value, arg):
return float(value) / float(arg)
def filter_mod(value, arg):
return int(value) % int(arg)
def filter_min(a, b):
return min(a, b)
def filter_max(a, b):
return max(a, b)
# converting
def filter_int(value):
return int(value)
# type
def filter_type(value):
return str(type(value))
# str
def filter_endswith(value, arg):
return value.endswith(arg)
def filter_quote(a):
return urlquote(a)

filters.py의 필터들을 추가하기 위해 settings.py에 다음과 같은 코드를 추가합니다.

jinja2.filters.FILTERS.update({
"getitem": filters.filter_getitem,
"getat": filters.filter_getat,
"notinappend": filters.filter_notinappend,
"union": filters.filter_union,
"divide": filters.filter_divide,
"mod": filters.filter_mod,
"min": filters.filter_min,
"max": filters.filter_max,
"int": filters.filter_int,
"type": filters.filter_type,
"endswith": filters.filter_endswith,
"quote": filters.filter_quote,
})

이렇게 하면 html에서 Jinja2 태그들 및 새롭게 추가한 Custom Filter들도 사용할 수 있습니다.

예를 들어서 다음 html 코드는

{% raw %}<input type="number" value="{{ -100|max(0) }}">{% endraw %}

추가한 max 필터를 거쳐서 <input type="number" value="0">이 되는 것입니다.