[컴][웹] 구글 앱 엔진 web app 대신에 Django 이용하기 1

장고이용하기, google app engine 에서 장고 이용하기


update : 2015-12-03








Google App Engine(GAE) 에서 Django 를 이용해 보려 한다. 그래서 자료를 찾아보니 아래 글들을 찾을 수 있었다. 내가 장고를 이용하려고 하는 이유는 webapp framework 에서 StringType 과 관련하여 assertion을 발생시켜서 utf-8 에 대한 처리를 할 수 없었다. ㅜ.ㅜ(http://i5on9i.blogspot.kr/2012/09/google-app-engine-utf-8-stringtype.html)

여하튼 Django 에서도 안될지 모르지만, 일단 도전해 본다. 그리고 Django 를 사용하는 데에는 여러 가지 이점이 있다.(Native-Django-on-App-Engine >> Advantages using native Django )

지금 부터는 Running Pure Django Projects on Google App Engine 를 바탕으로 글을 써 나갈 것이다.



Installation

먼저 아래 글을 보고 source code 를 만들자.
http://www.allbuttonspressed.com/projects/djangoappengine#installation
대략적으로 정리해서 얘기하면,
  • django-nonrel
  • djangoappengine
  • djangotoolbox
  • django-autoload
  • django-dbindexer
를 따로 받아서, 그 안에서 django, djangoappengine, dbindexer, djangotoolbox, autoload 폴더를 copy 해서
  • django-testapp
에 copy 해 넣어야 한다. 그러고 나서
manage.py runserver
를 해서 동작한다면, 제대로 파일을 구성한 것이다.(참고용 파일 download)

기본적으로 아래와 같은 구조가 된다.
image

추가로, app.yaml 에 application: APP_NAME 부분만 자신의 app_id 로 수정해 주도록 하자. 이 부분이 다르면 deploy 할 때(google app engine 에 업로드할 때), 해당 id가 존재하지 않는다며 error를 발생시킨다.



Django 의 파일 구성

Django 에서는 project 와 app 의 개념이 있다. app engine 에서 얘기하는 app 이 Django(장고) 에서는 project 라고 보면 된다. app 은 project 를 구성하는 요소로, 만약 한 사이트 내에 방명록, 사진첩이 있다고 한다면, 방명록, 사진첩은 각각의 app 인 것이고, 사이트는 project 가 된다.

Django 의 project 는 기본적으로 4개의 파일로 되어 있다.
  • __init__.py : python 에게 package라고 얘기해주는 부분
  • urls.py : url 을 해당하는 함수로 mapping 시켜준다.
  • settings.py : project 와 관련된 설정
  • manage.py : app 들을 위한 커맨드 라인 인터페이스
그리고 각 app 은 보통 하나의 folder 로 되어 있다. 그리고 이 app 들도 기본적으로 4가지 파일을 갖는다.
  • __init__.py : python 에게 package라고 얘기해주는 부분
  • models.py : data 모델
  • views.py : handler 들을 요청한다. 
  • tests.py : unit test 들(권고사항이다.)
대략의 파일구조는 아래와 같다.
/project
  +----- app_folder
  +         + __init__.py
  +         + models.py
  +         + views.py
  +         + tests.py
  +
  +------ __init__.py 
  +------ urls.py 
  +------ settings.py 
  +------ manage.py 

그럼 이제 실제 생성을 해보도록 하자. Django 에서는 script 를 제공하기 때문에 script 를 사용하자.

위에서 알려준 django-testapp 을 사용한다면, 기본적으로 django-guestbook 이라는 project 와 guestbook 이라는 app 이 만들어져 있는 것이라고 보면 된다. 그래서 아래의 명령이 굳이 필요하진 않지만, 알아두도록 하자.


project 만들기

프로젝트는 django-admin.py 를 이용해 만들 수 있다.

d:\eclipse\goolgeapp>c:\Python27\Scripts\django-admin.py startproject muchart


app 만들기

앱 파일은 manag.py 를 이용해 만들 수 있다.

d:\eclipse\goolgeapp>cd muchart

d:\eclipse\goolgeapp\muchart>manage.py startapp chart


Models

Model 부분은 건너뛴다. 내가 만들고 있는 녀석에서는 아직 DB가 필요하지 않아서 건너 뛴다. 궁금하신 분은 일단 https://developers.google.com/appengine/articles/django-nonrel#md 로 가서 보자.

아래 post 가 추가됐다. model 과 관련된 사항을 접해 볼 수 있다.






Request Handlers

wep app framework 에서는 request handler 가 하나의 class 였다. 하지만 Django 에서는 그저 하나의 함수로 처리된다. 그리고 request handler 라는 명칭 대신에 view 라고 부른다.

direct_to_template() 은 template 을 사용해서 화면에 뿌려주는 함수이다. request 를 왜 넘겨주는지는 아직 모르겠다. 일단 request 를 첫번째 parameter 로 넘어가게 되고, 그 다음에 template file 이름(template_muchart.html), 그 다음은 template 안에서 사용할 변수들이다.(greetings, from)

template file 의 path 의 기본 경로는 settings.py 에 있는
TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'templates'),)
이다.


#!/usr/bin/env python
# -*- coding: utf-8 -*-


from django.core.cache import cache
from django.views.generic.simple import direct_to_template


def musicChartPage(request):

    testval = {'melon':['m1' ,'m2','m3'],
                   'billboard':v2
                }

    chartNameList = {'melon', 'billboard'}
    return direct_to_template(request,
                        'template_muchart.html',
                        {'chartdata': testval,
                        'chartname': chartNameList}
                    )

이제 이 list_greetings() 를 특정 URL 에 묶어줘야 한다. 그 작업을 urls.py(django_project/app_folder/urls.py) 에서 해 주게 된다.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.conf.urls.defaults import *

urlpatterns = patterns('muchart.views',   #./muchart/views.py
    (r'^$',     'list_greetings'),
    (r'^sign$', 'create_greeting'),
)

그런데 이 app 아래에 있는 urls.py(settings.py, ROOT_URLCONF = 'urls' 와 연관이 있다.) 는 다시 project 폴더내의 urls.py(django_project/urls.py) 에서 app 폴더에 있는 urls.py 를 사용한다고 설정 해 주어야 한다. 그것을 가능하게 해 주는 것이 include 이다. 아래 그림을 보면,
r'^muchart/$', include('muchart.urls')
부분이
http://appenginedomain.com/muchart/    ---> project_folder/muchart/urls.py
로 연결시켜 주는 것이다.

image

여기서 주의할 점은
r'^muchart/$', include('muchart.urls')
 위 부분이다. 지금 r'^muchart/$' 로 설정을 해 놓은 것은 url 중에 정확히
http://appenginedomain.com/muchart/
에만 mapping 시킨다는 뜻이다. 여기서 중요한 것은 "$" 인데 이녀석을 없애야 한다. 이녀석을 없애야 뒤에 붙는 부분에 대해서 muchart.urls 를 참고한다는 뜻이된다. 만약 이대로 $ 를 붙이게 되면, /muchart/ 이후에 url 에 대한 처리를 하지 않는다.
r'^muchart/', include('muchart.urls')
만약 $를 없애지 않고, muchart/ 뒤에 붙는 것 까지 가능하게 하고 싶다면 아마도 pattern을 아래와 같이 수정해 줘야 할 것이다.(test 는 해보지 못했다. ^^;;;)(ref. 2 를 참고하자.)
r'^muchart/.*?$', include('muchart.urls')


settings.py 에 우리가 만들어 놓은 app 의 이름, 'muchart', 을 넣어놔야 한다.

SECRET_KEY = '=r-$b*8hglm+858&9t043hlm6-&6-3d3vfc4((7yd0dbrakhvi'

INSTALLED_APPS = (
#    'django.contrib.admin',
    'django.contrib.contenttypes',
    'django.contrib.auth',
    'django.contrib.sessions',
    'djangotoolbox',
    'autoload',
    'dbindexer',

    # djangoappengine should come last, so it can override a few manage.py commands
    'djangoappengine',
    
    # my app
    'muchart',
)

이제 runserver 를 해서 서버를 구동시켜 보자.
c:\guestbook>manage.py runserver [8080]

그리고 브라우저를 이용해서 server 로 접근을 시도 해 보자. 주의할 점은 기본 포트가 8000 이라는 점이다. 기본적으로 예전에 eclipse 에서 webapp 을 테스트 할 때 기본 경로가 localhost:8080 였기에 습관적으로 8080으로 접근하는 경우가 있으니 주의하기 바란다.

참고로 포트를 바꾸고 싶다면, 뒤에 포트번호를 넣어주면 된다.[ref.1]

접속이 되면 아래화면이 나올 것이다. 아래 pattern 에 대한 결과물이다.
(r'^$', 'django.views.generic.simple.direct_to_template',
     {'template': 'home.html'}),
image



PIL Warning 없애기

server를 실행시키니 Warning 중에 Python Image Library 에 대한 warning 이 있었다. 구글 앱 엔진 문서에서도 Images API 의 경우 PIL 을 사용하기 때문에 설치해야 한다고 한다. 당장 필요한 것은 아니지만 일단 설치 해 놨다. 아래 경로에 가서 .exe를 다운받고 실행하면 된다.
PIL 1.1.7 설치 : http://www.pythonware.com/products/pil/
그럼 아래와 같이 Warning 이 살아진 것을 확인할 수 있다.

d:\mine\programming\eclipse\goolgeapp\guestbook\src>manage.py runserver
WARNING:root:The rdbms API is not available because the MySQLdb library could not be loaded.
WARNING:root:Could not read search indexes from e:\temp\dev_appserver.searchindexes
WARNING:root:Could not initialize images API; you are likely missing the Python "PIL" module. ImportError: No module named _imaging
INFO:root:Checking for updates to the SDK.
INFO:root:The SDK is up to date.
WARNING:root:Could not read search indexes from e:\temp\dev_appserver.searchindexes
WARNING:root:Could not initialize images API; you are likely missing the Python "PIL" module. ImportError: No module named _imaging
INFO:root:Running application dev~ctst on port 8000: http://127.0.0.1:8000
INFO:root:Admin console is available at: http://127.0.0.1:8000/_ah/admin
^C
d:\mine\programming\eclipse\goolgeapp\guestbook\src>manage.py runserver
WARNING:root:The rdbms API is not available because the MySQLdb library could not be loaded.
WARNING:root:Could not read search indexes from e:\temp\dev_appserver.searchindexes
INFO:root:Checking for updates to the SDK.
INFO:root:The SDK is up to date.
WARNING:root:Could not read search indexes from e:\temp\dev_appserver.searchindexes
INFO:root:Running application dev~ctst on port 8000: http://127.0.0.1:8000
INFO:root:Admin console is available at: http://127.0.0.1:8000/_ah/admin


Eclipse 사용하기

Configuring Eclipse on Windows to Use With Google App Engine
여기에 있는 대로 따라 하고 나서,

  1. src 폴더에 guestbook 의 src 부분을 통째로 옮기고, 
  2. run configuration 의 Main Module 을 manage.py 로 지정해 주자.

그러고 나서 실행을 하면
Exception: Could not get appid. Is your app.yaml file missing? Error was: No module named simplejson
이라는 error 가 뜬다. 에서 얘기하는 것처럼 PYTHONPATH 에 google-appengine 의 path 가 들어간 것이 문제인 듯 하다.
Project >> Property >> PyDev - PYTHONPATH >> External Libraries >> ...\google_appengine 부분만 없애자.
그러면 이제 argument 부분에 runserver 를 넣어주고, 실행하면 된다.


References

  1. The development server : changing the port
  2. http://biohackers.net/wiki/RapidWebDevelopmentByDjango

댓글 없음:

댓글 쓰기