113
This session brought to you by SMARTSTUDY Django In Action

SMARTSTUDY Django 오픈 세션 2012-08

Embed Size (px)

DESCRIPTION

스마트스터디가 2012-08-16, 17 양일간 진행한 초심자를 위한 Django 오픈 세션에서 사용한 키노트 입니다.

Citation preview

Page 1: SMARTSTUDY Django 오픈 세션 2012-08

This session brought to you by SMARTSTUDY

Django In Action

Page 2: SMARTSTUDY Django 오픈 세션 2012-08

@lqez

2001-2006 NHN

2007-2010 NPLUTO

2010-현재 SMARTSTUDY

게임 개발자로 시작,

10년간 업계에서 구르다 지금은

걍 카페코딩 좋아하는 SCV.

박현우

Page 3: SMARTSTUDY Django 오픈 세션 2012-08

2010년 설립,

삼성출판사의 자회사

게임 업계에서 실컷 굴러본 경력!

+ 실력과 열정 넘치는 멋진 신입!

유아동 애플리케이션 +

만화, 동영상, 게임이 주력 사업.

양질의 콘텐츠를 수급하여,

좋은 서비스를 만드는 것이 목표!

스마트스터디

Page 4: SMARTSTUDY Django 오픈 세션 2012-08

OK, 회사 소개는거기까지.

Page 5: SMARTSTUDY Django 오픈 세션 2012-08

•Django 소개

•장단점

•우리는 왜?

•직접 경험하기

Session A

Page 6: SMARTSTUDY Django 오픈 세션 2012-08

역사

•Lawrence.com PHP 기반 웹사이트 유지보수를 위해.1

•개발자가 좋아하던 기타리스트인 Django Reinhardt 의 이름을 따서 지음.

[1] http://www.quora.com/What-is-the-history-of-the-Django-web-framework

Page 7: SMARTSTUDY Django 오픈 세션 2012-08

특징

• Full Stack Framework

•웹 페이지를 만들기 위한 대부분의 요소가 포함되어 있음.

•HTTP Request / Response 처리, URL 패칭

•템플릿 엔진

•ORM

•Lawrence.com 은 언론 / 뉴스 사이트.

•개발 당시 부르던 내부 이름은 ‘The CMS’.

•따라서, Admin 프레임워크가 잘 갖춰져 있다.

Page 8: SMARTSTUDY Django 오픈 세션 2012-08

역할

Web ServersUsers Web Application Data

QuerySetHTML PageJSON Result

HTTP Response

http://foo.comHTTP Request

Parsing Query

Page 9: SMARTSTUDY Django 오픈 세션 2012-08

역할

Web ServersUsers Web Application Data

QuerySetHTML PageJSON Result

HTTP Response

http://foo.comHTTP Request

Parsing Query

Django

WSGI

URLDispatcher

ORM

SerializerTemplateEngine

Page 10: SMARTSTUDY Django 오픈 세션 2012-08

역할, 그리고

Web ServersUsers Web Application Data

QuerySetHTML PageJSON Result

HTTP Response

http://foo.comHTTP Request

Parsing Query

Django

WSGI

URLDispatcher

ORM

SerializerTemplateEngine

Cache BackendAuthentication& Authorization

Internalization& Localization Forms Logging

RAW SQL

Security

Aggregation

DatabaseRouter

Admin Page

Testing

ErrorReporting

Sessions& Cookies

Page 11: SMARTSTUDY Django 오픈 세션 2012-08

... 거기에 더해

http://www.djangopackages.com/

Page 12: SMARTSTUDY Django 오픈 세션 2012-08

그래서,

Django is

Full Stack Web Framework

Page 13: SMARTSTUDY Django 오픈 세션 2012-08

그런데,

Web ServersUsers Web Application Data

QuerySetHTML PageJSON Result

HTTP Response

http://foo.comHTTP Request

Parsing Query

Django

WSGI

URLDispatcher

ORM

SerializerTemplateEngine

Cache BackendAuthentication& Authorization

Internalization& Localization Forms Logging

RAW SQL

Security

Aggregation

DatabaseRouter

Admin Page

Testing

ErrorReporting

Sessions& Cookies

Jinja 2

SQLAlchemy

BDDToolkit

Page 14: SMARTSTUDY Django 오픈 세션 2012-08

그런데,

Web ServersUsers Web Application Data

QuerySetHTML PageJSON Result

HTTP Response

http://foo.comHTTP Request

Parsing Query

Django

WSGI

URLDispatcher

ORM

SerializerTemplateEngine

Cache BackendAuthentication& Authorization

Internalization& Localization Forms Logging

RAW SQL

Security

Aggregation

DatabaseRouter

Admin Page

Testing

ErrorReporting

Sessions& Cookies

Jinja 2

SQLAlchemy

BDDToolkit

FAILED

Page 15: SMARTSTUDY Django 오픈 세션 2012-08

대안은?

•Werkzeug

•The Python WSGI Utility Library

• HTTP Request parsing / Response objects

• URL Dispatching

•Flask

•a micro-framework for Python based on Werkzeug

• Jinja 2 / Unit test / RESTful dispatching / Cookies

•국내에선,

• 패션 SNS - StyleSha.re

• http://engineering.stylesha.re/post/28761152299/styleshare-service-stack

• 모바일 소셜 포인트 카드 - DoDo / Spoqa 등이 사용중.

• http://spoqa.github.com/2012/01/16/wsgi-and-flask.html

Page 16: SMARTSTUDY Django 오픈 세션 2012-08

장단점

• Full Stack Framework

•장점 : 하나만 배우면 된다.

•단점 : 하나라도 제대로 이해하고 쓰기는 어렵다.

• Micro Framework

•장점 : 레고를 조립하듯 입맛대로 서비스를 구성할 수 있다.

•단점 : 뭐든지 찾아써야 한다.

Page 17: SMARTSTUDY Django 오픈 세션 2012-08

우리는 왜 Django를 선택했나.

•PHP로 더 이상 심각한 웹 개발을 하고 싶지 않다.

•딱히 싫어하는건 아니지만...

•왜 Python을?

•예전부터 써봤었고,

•각종 스크립트도 작성해서 쓰고 있었기에,

•웹 개발을 위해 별도로 Ruby나 Perl 등을 배우고 싶진 않다!

•하지만 웹 개발 전문가라 부를 사람이 없었음.

•와중에 10분만에 Django로 블로그 만들기 등을 보게 됨.

•http://www.lightbird.net/dbe/blog.html

Page 18: SMARTSTUDY Django 오픈 세션 2012-08

이거다! 선택의 여지가 없다!

Page 19: SMARTSTUDY Django 오픈 세션 2012-08

아... 안돼!

•아쉬운 점

•생각보다 정적 페이지 구성이 없음.

•애초에 Heavy AJAX 형태의 웹 서비스를 위한 구조가 아님.

• Paginator 같은 건 당연히 필요 없음.

•폼 처리가 거의 없다보니 매력 감소.

•기본 제공 관리 페이지가 우리에게 그리 쓸만하지 않음.

• User가 10만명이 넘어가는데, 해당 모델을 포함한 관리 페이지에서 10만개의 OPTION 태그로 그냥 출력해버리는 대범함... 당연히 엄청 느림.

Page 20: SMARTSTUDY Django 오픈 세션 2012-08

Django 장점 정리

1. 어쨌거나 웹 개발의 껍질만 배우고도 시작할 수 있다.

2. 한국어/한글로 된 도서도 있다! (...)

3. 각종 추가 모듈의 도움으로 간편하게 기능 확장!

4. 가볍게 데이터를 읽고 쓰기엔 기본 ORM도 나쁘지 않다.

5. 기본 템플릿 엔진도 그럭저럭 쓸만함.

6. 썩어도 준치, 없는 것보단 나은 기본 관리 페이지.

Page 21: SMARTSTUDY Django 오픈 세션 2012-08

Django 장점 정리

1. 어쨌거나 웹 개발의 껍질만 배우고도 시작할 수 있다.

2. 한국어/한글로 된 도서도 있다! (...)

3. 각종 추가 모듈의 도움으로 간편하게 기능 확장!

4. 가볍게 데이터를 읽고 쓰기엔 기본 ORM도 나쁘지 않다.

5. 기본 템플릿 엔진도 그럭저럭 쓸만함.

6. 썩어도 준치, 없는 것보단 나은 기본 관리 페이지.

시작한국어

추가 모듈기본 ORM

기본 템플릿관리 페이지

Page 22: SMARTSTUDY Django 오픈 세션 2012-08

하지만 여러분에겐,

•먼저 삽질한 스마트스터디가 미약하나마 있습니다.

•오늘 실습이 선택에 도움이 되길 바랍니다.

•페이스북 그룹도 있더군요.

•https://www.facebook.com/groups/django/

•꽤 활발합니다!

•IRC도 있습니다.

•#django / irc.ozinger.org

•하루 종일 아무도 말 안합니다...

Page 23: SMARTSTUDY Django 오픈 세션 2012-08

어쨌든우리는오늘웹툰을만들껍니다.

웹툰 화면은 네이버 웹툰(http://m.comic.naver.com)에서 발췌.

Session B

Page 24: SMARTSTUDY Django 오픈 세션 2012-08

...물론 현실은,

대략 이 정도...?

모든 이미지는 http://www.projectcartoon.com/ 에서 발췌.

Page 25: SMARTSTUDY Django 오픈 세션 2012-08

Step 0. 알고가기

> dir$ ls

•터미널 / 쉘에서 직접 실행하기 ( 초록색 배경 )

# 이미 입력되어 있던 소스 - 하얀색from webtoon.models import *(...) - 생략된 부분

# 새로 입력해야 하는 소스 - 노란색def home(request): return HttpResponse(output)

•소스 수정 ( 검은색 배경 )

•대부분의 경우 덮어쓰기 보다는 부분 수정이 많으니 주의해주세요.

Page 26: SMARTSTUDY Django 오픈 세션 2012-08

•Python은 들여쓰기(Indentation)을 탭, 또는 빈칸으로 합니다.

•하나의 소스 파일 내에서는 같은 들여쓰기 규칙을 유지합니다.

•섞어 쓰면 문법 오류가 발생.

•실습에서 .py / .html 파일은 모두 UTF-8 인코딩을 사용합니다.

•.py 에서도 한글을 사용하려면 아래 내용을 첫 줄에 넣습니다.

# -*- coding: utf-8 -*-

Page 27: SMARTSTUDY Django 오픈 세션 2012-08

Step 1. 준비

•Python

•setuptools / pip

•VirtualEnv / VirtualEnvWrapper

•소개 : http://blog.naver.com/ez_/140138625021

Page 28: SMARTSTUDY Django 오픈 세션 2012-08

•Windows

•기본으로 Python이 없으니, Python부터 설치합니다. 2.7을 선택해주세요.

• http://python.org/download/

•인스톨러를 통해 편리하게 설치할 수 있습니다.

•환경 변수 PATH에 아래 경로를 추가합니다.

• C:\Python27;C:\Python27\Scripts;

•환경 변수 PYTHONHOME을 지정합니다.

• C:\Python27

• http://pypi.python.org/pypi/setuptools

•32bit : http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11.win32-py2.7.exe 를 다운받아 실행.

•64bit : http://peak.telecommunity.com/dist/ez_setup.py 를 다운받아 python ez_setup.py 로 실행.

Page 29: SMARTSTUDY Django 오픈 세션 2012-08

•Windows (이어서 계속)

> easy_install pip> pip install virtualenvwrapper-win

•OS X / Linux

$ sudo easy_install pip$ sudo pip install virtualenvwrapper$ source /usr/local/bin/virtualenvwrapper.sh

•OS X 에서 distutils 오류 발생시, 아래 명령어 수행.

$ sudo touch /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/__init__.py

http://stackoverflow.com/questions/3129852/python-cant-locate-distutils-path-on-mac-osx

Page 30: SMARTSTUDY Django 오픈 세션 2012-08

•OS X / Linux 에서 ~/.profile 에 아래 내용 추가

source /usr/local/bin/virtualenvwrapper.sh# 가상 환경 위치를 바꾸고 싶으면 WORKON_HOME 수정# 기본 위치는 ~/.virtualenvsexport WORKON_HOME=~/VirtualEnvs

Page 31: SMARTSTUDY Django 오픈 세션 2012-08

Step 2. Django 설치

•mkvirtualenv

•workon / deactivate

•pip install django

Page 32: SMARTSTUDY Django 오픈 세션 2012-08

$ mkvirtualenv webtoonNew python executable in webtoon/bin/pythonInstalling setuptools............done.Installing pip...............done.(...)

(webtoon)$ deactiviate

$ workon(...이미 생성된 가상 환경들의 목록...)

$ workon webtoon(webtoon)$

Page 33: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ pip install djangoDownloading/unpacking django Downloading Django-1.4.1.tar.gz (7.7Mb): ... Running setup.py egg_info for package django Installing collected packages: django Running setup.py install for django(...)Successfully installed djangoCleaning up...(webtoon)$

Page 34: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ pythonPython 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) >>> import django>>> django.VERSION(1, 4, 1, 'final', 0)>>>

•잘 설치되었는지 확인!

Page 35: SMARTSTUDY Django 오픈 세션 2012-08

•Windows

•copy <홈 디렉토리>\Envs\Lib\site-packages\django\bin\django-admin.py c:\Python27\Scripts\

•위와 같이 미리 복사해주시면 편합니다.

•보통 홈 디렉토리는 ‘C:\Document and settings\사용자 이름’

Page 36: SMARTSTUDY Django 오픈 세션 2012-08
Page 37: SMARTSTUDY Django 오픈 세션 2012-08

Step 3. 드디어 시작!

•django-admin.py startproject mysite

•python manage.py runserver

•https://docs.djangoproject.com/en/1.4/intro/

Page 38: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ django-admin.py(...)(webtoon)$ django-admin.py startproject mysite(webtoon)$ cd mysite/(webtoon)$ lsmanage.py mysite(webtoon)$ python manage.py runserverValidating models...

0 errors foundDjango version 1.4.1, using settings 'mysite.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CTRL-BREAK.

•Windows 의 경우,

•python c:\Python27\Scripts\django-admin.py ...

Page 39: SMARTSTUDY Django 오픈 세션 2012-08
Page 40: SMARTSTUDY Django 오픈 세션 2012-08

Step 4. 웹툰 시작

•django-admin.py startapp webtoon

•settings.py 의 INSTALLED_APP 에 추가

•urls.py 에 뷰 등록

Page 41: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ python manage.py startapp webtoon(webtoon)$ lsmanage.py mysite webtoon(webtoon)$

•App 을 project 와 같은 위치에 만드는 이유

•‘... it can be imported as its own top-level module, rather than a submodule of mysite.’

•https://docs.djangoproject.com/en/1.4/intro/tutorial01/#creating-models

Page 42: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # ... 'webtoon',)

Page 43: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3' 'NAME': 'mysite.db', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } }

Page 44: SMARTSTUDY Django 오픈 세션 2012-08

Step 5. 모델

•User

•Comic

•Episode

•Author

•Comment

Page 45: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/models.py

from django.db import models

class Author(models.Model): name = models.CharField(max_length=200) desc = models.TextField()

•https://docs.djangoproject.com/en/dev/ref/models/fields

Page 46: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ python manage.py syncdbCreating tables ...Creating table auth_permissionCreating table auth_group_permissionsCreating table auth_groupCreating table auth_user_user_permissionsCreating table auth_user_groupsCreating table auth_userCreating table django_content_typeCreating table django_sessionCreating table django_siteCreating table webtoon_author

You just installed Django's auth system, which means you don't have any superusers defined.Would you like to create one now? (yes/no): yesUsername (leave blank to use 'lqez'): lqezE-mail address: [email protected]: Password (again): Superuser created successfully.Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)(webtoon)$

Page 47: SMARTSTUDY Django 오픈 세션 2012-08

•OS X / Linux 에서 LANG 관련 오류가 발생한다면,

•LANG 환경 변수가 잘못 정의되어 있거나 비어있어서 발생.

•https://code.djangoproject.com/ticket/5846

•아래와 같이 임시로 환경 변수를 설정하여 문제 회피 가능.

$ export LANG=en_US.UTF-8$ export LC_CTYPE=en_US.UTF-8

Page 48: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ python manage.py shellPython 2.7.1 (r271:86832, Jul 31 2011, 19:30:53)(InteractiveConsole)>>> from webtoon.models import *>>>>>> new_author = Author()>>> new_author.name = "주호민">>> new_author.desc = "파주스님">>> new_author.save()>>>>>> authors = Author.objects.all()>>> authors[<Author: Author object>]>>>

Page 49: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/models.py

class Author(models.Model): name = models.CharField(max_length=200) desc = models.TextField()

def __unicode__(self): return self.name

(webtoon)$ python manage.py shell>>> from webtoon.models import *>>> authors = Author.objects.all()>>> authors[<Author: 주호민>]>>>

Page 50: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/models.py

class Author(models.Model): name = models.CharField(max_length=200) desc = models.TextField()

def __unicode__(self): return self.name

(webtoon)$ python manage.py shell>>> from webtoon.models import *>>> authors = Author.objects.all()>>> authors[<Author: 주호민>]>>>

Page 51: SMARTSTUDY Django 오픈 세션 2012-08

•Django 의 ORM 기능에 대한 소개는,

•https://docs.djangoproject.com/en/1.4/ref/models/querysets/

•https://docs.djangoproject.com/en/1.4/topics/db/queries/

Page 52: SMARTSTUDY Django 오픈 세션 2012-08

Step 6. 관리 페이지

•admin 모듈 추가.

•내가 만든 모델을 admin에 노출하기.

•ModelAdmin 상속 받아 확장하기.

•MEDIA / STATIC 파일 이해.

Page 53: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

INSTALLED_APPS = ( # ... # Uncomment the next line to enable the admin: 'django.contrib.admin', 'webtoon',)

•mysite/urls.py

from django.contrib import adminadmin.autodiscover()

urlpatterns = patterns('', # ... # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)),)

Page 54: SMARTSTUDY Django 오픈 세션 2012-08

(webtoon)$ python manage.py syncdbCreating tables ...Creating table django_admin_logInstalling custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)(webtoon)$

•관리자 페이지 이용을 위한 로그 테이블 생성

Page 55: SMARTSTUDY Django 오픈 세션 2012-08

•http://localhost:8000/admin

Page 56: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/admin.py (파일이 없으니 생성해주세요)

•대부분의 경우 runserver 에서 자동으로 다시 읽어주나,

•이 경우는 자동으로 읽어주지 않으니, 종료 후 다시 실행해주세요.

from webtoon.models import *from django.contrib import admin

admin.site.register(Author)

Page 57: SMARTSTUDY Django 오픈 세션 2012-08

•http://localhost:8000/admin

Page 58: SMARTSTUDY Django 오픈 세션 2012-08
Page 59: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/admin.py

class AuthorAdmin(admin.ModelAdmin): list_display = ('name', 'desc')admin.site.register(Author, AuthorAdmin)

Page 60: SMARTSTUDY Django 오픈 세션 2012-08
Page 61: SMARTSTUDY Django 오픈 세션 2012-08

•링크를 통해 완성된 소스를 받아주세요.

•webtoon/models.py

•https://gist.github.com/3367067

•webtoon/admin.py

•https://gist.github.com/3368666

(webtoon)$ python manage.py syncdbCreating tables ...Creating table webtoon_episodeCreating table webtoon_comicCreating table webtoon_commentInstalling custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)(webtoon)$

Page 62: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

•MEDIA_ROOT : 미디어 파일이 실제 저장될 위치

•MEDIA_URL : 어떤 URL로 미디어 파일을 전달할 것인가

•이미 settings.py 에 변수가 있으니, 찾아서 변경해주세요.

import os.pathMEDIA_ROOT = os.path.join(os.path.dirname(__file__),"media/")MEDIA_URL = '/media/'

Page 63: SMARTSTUDY Django 오픈 세션 2012-08
Page 64: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/urls.py

import os.pathurlpatterns = patterns('', ... (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__),'media')} ),)

•STATIC / MEDIA 파일 전달

•원래 Django 의 역할이 아님.

•개발 편의를 위해 django.views.static.serve 사용

•Production 에서는 절대 사용 금지!

Page 65: SMARTSTUDY Django 오픈 세션 2012-08
Page 66: SMARTSTUDY Django 오픈 세션 2012-08

•샘플 데이터베이스 및 파일 다운로드

•데이터베이스

•http://dl.dropbox.com/u/16168259/mysite.db

•manage.py 가 있는 위치에 있는 mysite.db 에 덮어 씌우세요.

•관리자 ID : test / PW : test

•이미지 파일

•http://dl.dropbox.com/u/16168259/comics.zip

•압축 해제 후, mysite/media/comics 안에 모든 jpg 파일을 복사해주세요.

•모든 이미지는 네이버와 각 작가분에게 저작권이 있습니다. (?)

Page 67: SMARTSTUDY Django 오픈 세션 2012-08

Step 7. 뷰와 템플릿

•뷰 준비하기

•템플릿 만들어보기

•상속된 템플릿

•템플릿 필터

•컨텍스트 프로세서

Page 68: SMARTSTUDY Django 오픈 세션 2012-08

•아래와 같은 URL로 웹 서비스를 하려고 합니다.

•웹툰 홈페이지

•/webtoon

•작가 페이지

•/webtoon/author/작가

•만화 페이지

•/webtoon/만화

•에피소드 페이지

•/webtoon/만화/에피소드

Page 69: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/urls.py

url(r'^webtoon/$', 'webtoon.views.home', name='webtoon'),url(r'^webtoon/author/(?P<author_id>\d+)/$', 'webtoon.views.author', name='author'),url(r'^webtoon/(?P<comic_id>\d+)/$', 'webtoon.views.comic', name='comic'),url(r'^webtoon/(?P<comic_id>\d+)/(?P<episode_id>\d+)/$', 'webtoon.views.episode', name='episode'),

url(r'^webtoon/$', 'webtoon.views.home', name='webtoon'),url(r'^webtoon/author/(\d+)/$', 'webtoon.views.author', name='author'),url(r'^webtoon/(\d+)/$', 'webtoon.views.comic', name='comic'),url(r'^webtoon/(\d+)/(\d+)/$', 'webtoon.views.episode', name='episode'),

•Named parameter

•처음엔 좀 복잡해 보이지만,

•의미 전달에 용이

Page 70: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py

from django.http import HttpResponse

def home(request): return HttpResponse('Home of webtoon service')

def author(request, author_id): return HttpResponse('Author %s page' % author_id)

def comic(request, comic_id): return HttpResponse('Comic %s page' % comic_id)

def episode(request, comic_id, episode_id): return HttpResponse('Episode %s of Comic %s page' % (episode_id, comic_id) )

Page 71: SMARTSTUDY Django 오픈 세션 2012-08

•웹툰 홈페이지

http://localhost:8000/webtoon

•작가 페이지

http://localhost:8000/webtoon/author/1

•만화 페이지

http://localhost:8000/webtoon/1

•에피소드 페이지

http://localhost:8000/webtoon/1/1

•URL 마지막에 자동으로 / 붙음.

settings.APPEND_SLASH = True

•HTTP 301 로 Redirection 시키므로, 원하지 않는 경우 url을 잘 설정하고 해당 기능을 꺼야 함.

Page 72: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py

from django.template.context import RequestContextfrom django.template.loader import get_template

def home(request): template = get_template('home.html')

variables = RequestContext(request, {}) output = template.render(variables)

return HttpResponse(output)

(...)

Page 73: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/home.html

•공용 템플릿은 프로젝트 디렉토리의 templates 에,

•앱의 템플릿은 앱 디렉토리의 templates 에 놔두면 좋습니다.

<html><head> <meta charset="utf-8" /> <title>Django 웹툰</title></head><body> <h1>Django 웹툰</h1> <p>Django 웹툰에 오신 것을 환영합니다.</p></body></html>

Page 74: SMARTSTUDY Django 오픈 세션 2012-08
Page 75: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/home.html

<html> <head> <title>Django 웹툰</title></head> <body> <h1>Django 웹툰</h1> <p>Django 웹툰에 오신 것을 환영합니다.</p> <ul> {% for episode in episodes %} <li>{{ episode.title }}</li> {% endfor %} </ul> </body> </html>

Page 76: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py

from webtoon.models import *

def home(request): template = get_template('home.html') episodes = Episode.objects.all() variables = RequestContext(request, { 'episodes': episodes, }) output = template.render(variables) return HttpResponse(output)

Page 77: SMARTSTUDY Django 오픈 세션 2012-08
Page 78: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/home.html

(...)<li> <a href="{% url episode episode.comic.id episode.id %}"> {{ episode.title }} </a></li>(...)

Page 79: SMARTSTUDY Django 오픈 세션 2012-08
Page 80: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/episode.html

<html>

<head>

<title>{{ episode.title }} :: {{ episode.comic.title }} :: Django 웹툰</title></head>

<body>

<h1><a href="{% url webtoon %}">Django 웹툰</a></h1> <h2><a href="{% url comic episode.comic.id %}">{{ episode.comic.title }}</a></h2>

<h3>{{ episode.title }}</h3>

<img src="{{ episode.img_file.url }}">

</body>

</html>

Page 81: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py

def episode(request, comic_id, episode_id): template = get_template('episode.html') episode = Episode.objects.get(id=episode_id) variables = RequestContext(request, { 'episode': episode, }) output = template.render(variables) return HttpResponse(output)

Page 82: SMARTSTUDY Django 오픈 세션 2012-08
Page 83: SMARTSTUDY Django 오픈 세션 2012-08

•공통된 부분을 부모 템플릿으로 생성

•상속 : {% extends “base.html” %}

•포함 : {% include “part.html” %}

•대체 : {% block foo %} {% endblock %}

• {{ block.super }} 로 부모의 내용을 포함 가능

<html><head><title>{% block title %}Django 웹툰{% endblock %}</title>{% block head %}{% endblock %}</head><body>{% block content %}{% endblock %}</body></html>

•webtoon/templates/base.html

Page 84: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/episode.html

{% extends "base.html" %}

{% block title %}

{{ episode.title }} :: {{ episode.comic.title }} :: Django 웹툰{% endblock %}

{% block content %}

<h1><a href="{% url webtoon %}">Django 웹툰</a></h1> <h2><a href="{% url comic episode.comic.id %}">{{ episode.comic.title }}</a></h2>

<h3>{{ episode.title }}</h3>

<img src="{{ episode.img_file.url }}">

{% endblock %}

Page 85: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/copyright.html

<div>모든 만화의 저작권은 각 작가에게 있습니다.</div>

•webtoon/templates/base.html

<html><head><title>{% block title %}Django 웹툰{% endblock %}</title>{% block head %}{% endblock %}</head><body>{% block content %}{% endblock %}{% include "copyright.html" %}</body></html>

Page 86: SMARTSTUDY Django 오픈 세션 2012-08

•더 해보기

•/webtoon/author 뷰 구현

•작가 소개

•작가가 그린 만화 링크

•/webtoon/comic 뷰 구현

•해당 만화 작가 페이지로의 링크

•해당 만화에 속해있는 에피소드 출력하기

•/webtoon개선

•최근 만화 n개만 출력

•작가별 링크

Page 87: SMARTSTUDY Django 오픈 세션 2012-08

Step 9. 사용자 입력

•로그인 / 로그아웃

•폼 처리

•댓글 달기

Page 88: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/urls.py

•기본 로그인 모듈의 경로를 모두 추가

•로그인 : /accounts/login

•로그아웃 : /accounts/logout

(r'^accounts/', include('django.contrib.auth.urls')),

Page 89: SMARTSTUDY Django 오픈 세션 2012-08

•http://localhost:8000/accounts/login

Page 90: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

•공용 템플릿들을 보관하기 위해 디렉토리 경로 추가

TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__),"templates"),)

•mysite/templates/registration/login.html

{% extends "base.html" %}{% block content %}<form method="post">{% csrf_token %}{{ form.as_p }}<input type="submit" value="로그인" /></form>{% endblock %}

Page 91: SMARTSTUDY Django 오픈 세션 2012-08
Page 92: SMARTSTUDY Django 오픈 세션 2012-08

•왜 로그인 이후에 /accounts/profile 로 가는가?

Page 93: SMARTSTUDY Django 오픈 세션 2012-08

•mysite/settings.py

•LOGIN_URL : 로그인 페이지

•LOGIN_REDIRECT_URL : 로그인 이후 갈 페이지

•https://docs.djangoproject.com/en/1.4/topics/auth/

LOGIN_URL = '/accounts/login/'LOGIN_REDIRECT_URL = '/webtoon/'

Page 94: SMARTSTUDY Django 오픈 세션 2012-08

•로그인 여부 확인

•in Python : if request.user.is_authenticated():

•in Template : {% if user.is_authenticated %}

Page 95: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/comment.html

{% if user.is_authenticated %} <p>{{ user.username }} 사용자로 이름으로 댓글 달기</p> <form method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="댓글" /> </form>{% else %} <p> <a href="{% url login %}"> 댓글을 달려면 로그인 해주세요. </a> </p>{% endif %}

Page 96: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/episode.html

{% block content %} (...) <img src="{{ episode.img_file.url }}"> {% include "comment.html" %}{% endblock %}

•webtoon/forms.py

•https://docs.djangoproject.com/en/1.4/topics/forms/

from django import forms

class CommentForm(forms.Form): msg = forms.CharField(max_length=200)

Page 97: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.pyfrom django.http import HttpResponseRedirectfrom datetime import datetimefrom webtoon.forms import *(...)def episode(request, comic_id, episode_id): template = get_template('episode.html') episode = Episode.objects.get(id=episode_id)

if request.method == 'POST': form = CommentForm(request.POST) if form.is_valid(): comment = Comment() comment.msg = form.cleaned_data['msg'] comment.user = request.user comment.episode = episode comment.written_date = datetime.now() comment.save() return HttpResponseRedirect(request.get_full_path()) else: form = CommentForm()

Page 98: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py (이전 페이지에 이어서)

(...) variables = RequestContext(request, { 'episode': episode, 'form': form, }) output = template.render(variables) return HttpResponse(output)

Page 99: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/views.py

(...)def episode(request, comic_id, episode_id): # ... comments = Comment.objects.filter(episode=episode_id)

variables = RequestContext(request, { 'episode': episode, 'form': form, 'comments': comments, })

Page 100: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/comment.html

(...){% if comments %} 댓글( 총 {{ comments|length }} 개 ) <ul> {% for c in comments %} <li>{{ c.user.username }} : {{ c.msg }} / {{ c.written_date }}</li> {% endfor %} </ul>{% endif %}

•length 등, 변수에 | (pipe)로 연결되는 것은 ‘템플릿 필터’

•템플릿에서 간단한 처리가 가능한 것들은 필터로 처리

•https://docs.djangoproject.com/en/1.4/ref/templates/builtins/

Page 101: SMARTSTUDY Django 오픈 세션 2012-08

•로그인하고 나서 다시 원래 자리로 돌아오려면?

•next 인자로 URL 전달 - 근데 템플릿에서 현재 URL을 모른다?

•TEMPLATE_CONTEXT_PROCESSOR

•모든 템플릿에 전달되는 기본 값들의 집합

•필요한 경우 컨텍스트 프로세서를 추가해서 사용하면 됨.

•mysite/settings.py

from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP

TEMPLATE_CONTEXT_PROCESSORS = TCP + ( 'django.core.context_processors.request',)

Page 102: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/templates/comment.html

{% if user.is_authenticated %} (...){% else %} <p> <a href="{% url login %}?next={{ request.get_full_path }}"> 댓글을 달려면 로그인 해주세요. </a> </p>{% endif %}(...)

Page 103: SMARTSTUDY Django 오픈 세션 2012-08

•어? 가입 페이지가 없잖아?! 일단 shell로 추가해보자.

(webtoon)$ python manage.py shellPython 2.7.1 (r271:86832, Jul 31 2011, 19:30:53)(InteractiveConsole)>>> from django.contrib.auth.models import User>>> user = User.objects.create_user(... username='anonymous',... email='[email protected]',... password='1234')>>> user.save()>>>

Page 104: SMARTSTUDY Django 오픈 세션 2012-08

•더 해보기

•폼을 이용한 가입 페이지 만들기

•from django.contrib.auth.forms import UserCreationForm

•http://www.djangobook.com/en/2.0/chapter14/

•댓글 달기를 POST 대신 AJAX로 처리해보기

•댓글이 많은 경우 어떻게 할 것인가?

•/webtoon/comic_id/episode_id/comments

Page 105: SMARTSTUDY Django 오픈 세션 2012-08

Step 10. 마무리

•css 적용

•admin 페이지에 검색 기능, 리스트 필터 등 넣어보기

•django-debug-toolbar

Page 106: SMARTSTUDY Django 오픈 세션 2012-08

•webtoon/static/css/webtoon.css

•* { font-family: sans-serif; }

•webtoon/static/img/django.gif

•http://dl.dropbox.com/u/16168259/django.gif

•webtoon/templates/base.htmlhtml><head> <meta charset="utf-8" /> <title>{% block title %}Django 웹툰{% endblock %}</title> <link rel="stylesheet" href="{{ STATIC_URL }}css/webtoon.css"> {% block head %}{% endblock %}</head><body> {% block content %}{% endblock %} {% include "copyright.html" %} <img src="{{ STATIC_URL }}img/django.gif"></body></html>

Page 107: SMARTSTUDY Django 오픈 세션 2012-08

•STATIC_ROOT / STATIC_URL

•템플릿과 마찬가지로 앱 별 STATIC 파일과,

•전역으로 사용할 STATIC 파일은 별도로 관리.

STATICFILES_DIRS = ( os.path.join(os.path.dirname(__file__),"static"),)

•어? MEDIA 와는 다르게 왜 되는거지?

•STATIC_URL 이 지정되어 있고,

•settings.STATICFILES_FINDERS 에 AppDirectoriesFinder 가 등록되어 있음.

•MEDIA와 마찬가지로, Production에서는 사용하지 마세요.

Page 108: SMARTSTUDY Django 오픈 세션 2012-08

•관리 페이지 기능 개선

•search_fields : 검색 대상

•ordering : 기본 정렬

•https://docs.djangoproject.com/en/1.4/ref/contrib/admin/

•webtoon/admin.py

class EpisodeAdmin(admin.ModelAdmin): list_display = ('comic', 'title', 'pub_date') search_fields = ['title','comic__title'] ordering = ['-pub_date']admin.site.register(Episode, EpisodeAdmin)

Page 109: SMARTSTUDY Django 오픈 세션 2012-08

•Django debug toolbar

•http://blog.naver.com/ez_/140162876100

(webtoon)$ pip install django-debug-toolbar

MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)INSTALLED_APPS += ('debug_toolbar',)INTERNAL_IPS = ('127.0.0.1',)DEBUG_TOOLBAR_PANELS = ( 'debug_toolbar.panels.version.VersionDebugPanel', 'debug_toolbar.panels.timer.TimerDebugPanel', 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', 'debug_toolbar.panels.headers.HeaderDebugPanel', 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', 'debug_toolbar.panels.template.TemplateDebugPanel', 'debug_toolbar.panels.sql.SQLDebugPanel', 'debug_toolbar.panels.signals.SignalDebugPanel', 'debug_toolbar.panels.logger.LoggingPanel', 'debug_toolbar.panels.profiling.ProfilingDebugPanel',)

Page 110: SMARTSTUDY Django 오픈 세션 2012-08
Page 111: SMARTSTUDY Django 오픈 세션 2012-08

집에서 더 해볼만한 것

•South 를 통해 기존 모델 변경해보기

•http://jcstyle.tistory.com/entry/django-migration-tool-South-%EC%9E%91%EC%97%85%EA%B8%B0

•별점 주기 기능 추가

•Rating Model 을 추가하는 것으로 시작.

Page 112: SMARTSTUDY Django 오픈 세션 2012-08

참여한 분들에게 바라는 점

•오늘 실습을 끝까지 진행하지 못했어도,

•환경은 구축되었으므로, 나머지를 끝까지 진행해주세요.

•주변에 많이 소개해주세요.

•스마트스터디는 이상한 회사다!

•블로그 등으로 써주시고, 저희 페이스북 페이지에 알려주세요 :D

Page 113: SMARTSTUDY Django 오픈 세션 2012-08

모두 수고하셨습니다!