Skip to content

Instantly share code, notes, and snippets.

@hyukkwonepic
Last active March 24, 2017 01:22
Show Gist options
  • Save hyukkwonepic/dfede87e3b219ea67c9caa5593c55945 to your computer and use it in GitHub Desktop.
Save hyukkwonepic/dfede87e3b219ea67c9caa5593c55945 to your computer and use it in GitHub Desktop.
장고 개요(Django at a glance)

장고 개요

장고는 빠르게 변화하는 신문사의 환경에서 개발되었기 때문에 일반적인 웹 개발 작업들을 빠르고 쉽게 만들 수 있도록 디자인되었습니다. 아래에서 데이터베이스 기반의 장고 어플리케이션을 작성하는 방법에 대한 간단한 개요를 살펴봅시다.

이 문서의 목표는 여러분에게 알맞는 기술적 상세를 제공함으로써 장고에 대한 충분한 이해를 드리는 것 입니다. 하지만 해당 문서는 단순히 튜토리얼이나 참조문서로서 의도된 것이 아니라 두 가지 모두 함께 제공됩니다! 프로젝트를 시작할 준비가 되었다면 바로 [튜토리얼을 시작]하거나 [상세 문서]로 이동하시면 됩니다.

모델을 설계하기

비록 여러분은 데이터베이스 없이 장고를 사용할 수 있지만, 파이썬 코드를 활용하여 데이터베이스를 설명할 수 있는 객체 관계형 매퍼가 포함되어 있습니다.

데이터 모델 구문에서는 모델을 표현하는 다양한 방법들이 제공됩니다 - 지금까지 수년간 많은 데이터베이스 스키마와 관련된 문제들을 해결해 왔습니다. 간단한 예를 보여드리죠:

mysite / news / models.py
from  django.db  import  models

class  Reporter ( models . Model ) : 
    full_name  =  models . CharField ( max_length = 70 )

    def  __str__ ( self ) :               # __unicode__ on Python 2 
        return  self . full_name

class  Article ( models . Model ) : 
    pub_date  =  models . DateField () 
    headline  =  models . CharField ( max_length = 200 ) 
    content  =  models . TextField () 
    reporter  =  models . ForeignKey ( Reporter ,  on_delete = models . CASCADE )

    def  __str__ ( self ) :               # __unicode__ on Python 2 
        return  self . headline

설치하기

다음으로, 커멘드라인 유틸리티에서 장고를 실행하여 자동으로 데이터베이스 테이블을 생성합니다:

$ python manage.py migrate

migrate커멘드는 사용가능한 모든 모델들을 찾고 기존에 존재하지 않는 테이블들을 여러분의 데이터베이스에 새로 생성함과 동시에 더욱 강력한 스키마 컨트롤을 부가적으로 제공합니다.

자동으로 생성되는 API를 즐겨봐요

이것만으로도 여러분은 데이터에 접근하기 위한 강력하고 자유로운 파이썬 API를 가지게 됩니다. API는 그때그때마다 생성되기 때문에 코드를 생성할 필요가 없죠.

# 'news'앱에서 생성한 모델을 불러옵니다.
>>> from news.models import Reporter, Article

# 시스템에는 아직 리포터 객체들이 없죠.
>>> Reporter.objects.all()
<QuerySet []>

# 새로운 리포터를 생성합니다.
>>> r = Reporter(full_name='John Smith')

# 해당 객체를 데이터베이스에 저장합니다. 저장할 때에는 save() 메소드를 명시적으로 실행해야합니다.
>>> r.save()

# 이제 해당 객체는 ID값을 가지죠.
>>> r.id
1

# 이제 새로운 리포터가 데이터베이스에 들어갔습니다.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# 각 필드는 파이썬 객체의 속성값으로 표시됩니다.
>>> r.full_name
'John Smith'

# 장고는 쩌는 데이터베이스 탐색 기능을 제공합니다.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

# 이렇게 기사(article)를 생성합니다.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# 이제 기사가 데이터베이스 내부에 있군요.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# Article 객체는 Reporter 객체에 관계가 설정되어 API로써 접근할 수 있습니다.
>>> r = a.reporter
>>> r.full_name
'John Smith'

#그리고 그 반대도 마찬가지죠: Reporter 객체 또한 Article 객체에 API 접근을 할 수 있습니다.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# The API follows relationships as far as you need, performing efficient
# 이 API는 여러분이 필요한 만큼 관계를 설정하면 효율적으로 그 관계를 따라가게 되죠. 
# (역주: 이해 불가 - JOINs for you behind the scenes)
# 아래 스크립트에서는 이름이 "John" 으로 시작되는 리포터들의 모든 기사들을 찾아줍니다.
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# 객체의 속성을 변경하여 save() 메쏘드를 호출합니다.
>>> r.full_name = 'Billy Goat'
>>> r.save()

# delete() 메쏘드로 객체를 삭제합니다.
>>> r.delete()

동적인 관리자 인터페이스: 단지 뼈대만을 세우지 않아요 - 온전한 집을 세웁니다

모델이 한번 정의되면 장고는 자동으로 전문적이며 제품으로써도 완벽한 [관리자 인터페이스] - 승인된 관리자 유저가 객체들을 생성, 변경 그리고 삭제할 수 있는 웹사이트 - 를 만들게 됩니다. 단지 모델을 관리자 사이트에 등록하기만 하면 되기 때문에 쉽죠:

mysite/news/models.py
from django.db import models

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
mysite/news/admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Article)

사이트의 편집은 직원, 고객, 또는 자신의 손으로 이루어지는 것이며, 컨텐츠의 관리만을 위해 백엔드 인터페이스를 만들고 싶지는 없다는 생각이 여기에 있습니다.

장고 어플리케이션을 만드는 일반적인 워크플로우는 바로 모델을 먼저 생성하고 관리자페이지를 가능한 한 빠르게 띄우는 것 입니다. 그러면 웹사이트 관리자(또는 클라이언트)들이 바로 데이터를 채우기 시작할 수 있죠. 그 다음에 데이터가 공개되는 방식을 개발합니다.

URL 설계하기

깔끔하고 품위(?)넘치는 URL 도식은 뛰어난 웹 어플리케이션의 중요한 특징입니다. 장고는 아름다운 URL디자인을 지향하며 URL에 .php 또는 .asp와 같은 지저분한 것들을 포함하지 않죠.

URL을 설계하기 위해면 먼저 URLconf라는 파이썬 모듈을 생성해야합니다. 이것은 애플리케이션의 목차에 있어서 URL 패턴과 파이썬 콜백 함수(callback function)을 연결하게 됩니다. URLconf는 또한 파이썬 코드와 URL을 분리(decouple)하는 기능또한 가지고 있습니다.

위에서 본 Reporter/Article에서 URLconf의 예시는 아래와 같습니다:

mysite/news/urls.py
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

위의 코드는 정규표현식을 사용한 URL과 파이썬 콜백 함수의 위치("view")를 연결(map)합니다. 여기서의 정규 표현식은 괄호를 사용하여 URL의 값들을 "포착(capture)" 하게 됩니다. 사용자가 페이지를 요청할 때, 장고는 각각의 패턴을 순서대로 살피게 되어 요청된 URL과 일치하는 첫번째 패턴에서 멈추게 됩니다.(만약 어떠한 패턴과 일치하지 않으면 특수케이스인 404 뷰를 호출하게 되죠.) 정규표현식은 로딩과 동시에 컴파일되기 때문에 이 과정은 엄청나게 빠르게 실행됩니다.

일단 한 정규표현식과 일치하면 장고는 주어진 뷰를 가져와 호출합니다. 이것은 기본적인 파이썬의 기능이죠. 그 후 각각의 뷰는 요청된 객체(요청된 메타데이터가 포함된)와 정규식에서 포착된 값을 받게 됩니다.

예를 들면, 만약 유저가 요청한 URL이 “/articles/2005/05/39323/" 와 같다고 하면, 장고는 news.views.article_detail(request, '2005', '05', '39323')라는 함수를 호출하게 됩니다.

뷰 작성하기

각 뷰는 두가지 역할을 하게됩니다: 요청된 페이지의 내용을 포함하는 HttpRespone 객체를 리턴하거나 Http404와 같은 예외 사항을 띄웁니다. 나머지는 여러분이 하지면 됩니다.

일반적으로 뷰는 매개 변수에 따라서 데이터를 불러오고, 템플릿을 가져와서 불러온 데이터를 템플릿에 렌더링합니다. 위에서 본 year_archive의 예시를 살펴봅시다:

mysite/news/views.py
from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

위의 예시는 장고의 [템플릿 시스템]을 사용하는데, 다양한 강력한 기능들을 가지고 있지만 비개발자들을 위해서 간단하게 구조되었습니다.

템플릿 설계하기

위의 코드는 news/year_archive.html 템플릿을 불러오고 있습니다.

장고는 템플렛의 반복과 중복을 최소화하기 위해 템플릿 검색 경로(template search path)를 가지고 있습니다. 여러분의 장고 세팅에서 템플릿을 선택하는 DIRS디렉토리 목록을 지정합니다. 만약 첫번째 디렉토리에 템플릿이 존재하지 않는다면 두번째를 찾게 되며 그 이후에도 이 과정이 계속 이어집니다.

만약 news/year_archive.html이 발견되었다고 가정해봅시다. 템플릿은 다음과 같이 쓰여져 있습니다:

mysite/news/templates/news/year_archive.html
{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
    <p>{{ article.headline }}</p>
    <p>By {{ article.reporter.full_name }}</p>
    <p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

변수들은 이중(二重) 중괄호로 감싸져있습니다. {{ article.headline }}은 "article의 headline 속성의 값을 불러오렴" 이라는 의미를 가집니다. 하지면 마침표(.)는 객체의 속성 뿐만아니라 딕셔너리의 키, 인덱스 그리고 함수를 호출하는 데에도 사용됩니다.

{{ article.pub_date|date:"F j, Y" }}에서는 유닉스 스타일의 파이프(|)를 사용한다는 것을 유념해주세요. 이것은 템플릿 필터(template filter)라고 불리는데 변수의 값을 필터링하는데 사용됩니다. 이 경우에는 date 필터가 파이썬 datetime 객체를 위에서 지정된 형식으로 포맷(format)합니다(PHP에서 date 함수와 비슷하죠).

필터는 원하는만큼 얼마든지 연결(chain) 할 수 있습니다. 심지어 파이썬 코드로 작성된 [사용자 정의 템플릿 필터]와 [사용자 정의 템플릿 태그]를 만들 수 있죠.

마지막으로 장고는 "템플릿 상속(template inheritance)"라는 개념을 사용합니다. 그것이 바로 {% extends "base.html" %}와 같은것이죠. 무슨 의미냐면, "먼저 'base'라는 이름의 템플릿을 불러오렴. 근데 이 템플릿은 겁나 많은 블럭들이 지정되어 있는데 아래의 블럭들로 블럭들을 채우면 돼" 라는 의미를 가지게 됩니다. 간단하게 말하면, 템플릿 내에서의 수많은 중복 내용을 없앨 수 있습니다: 각 템플릿은 각각의 템플릿에 해당하는 내용만을 담으면 되기 때문이죠.

아래는 "base.html" 템플릿인데, 정적 파일(static file)에 대한 내용을 담고있습니다:

mysite/templates/base.html
{% load static %}
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <img src="{% static "images/sitelogo.png" %}" alt="Logo" />
    {% block content %}{% endblock %}
</body>
</html>

이 템플릿은 사이트의 느낌적인 요소(로고를 포함한)를 정의하고 있으며, 그 사이에 하위 템플릿들을 위한 "구멍"들을 담고 있습니다. 그렇기 때문에 사이트의 디자인을 바꿀때 해당 템플릿 파일(base 템플릿 파일) 하나만을 변경하면 됩니다.

다른 시스템을 사용하고 싶으시다면 장고의 템플릿 시스템을 사용할 필요는 없다는 점에 유의해 주세요. 물론 장고의 템플릿 시스템이 특별히 장고의 모델 레이어와 원활히 통합되기는 하지만 꼭 사용해야 할 필요는 없습니다. 비슷한 양상의 주제로, 장고의 데이터베이스 API를 반드시 사용할 필요또한 없습니다. 다른 데이터베이스 레이어를 사용하거나, XML파일을 읽어들일 수도 있고, 디스크에서 파일을 읽어도 됩니다. 무엇이든 원하는데로 하시면 됩니다. 각각의 장고의 요소들 - 모델, 뷰 그리고 템플릿-은 분리하여 사용될 수 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment