Django 훑어보기

Django는 급한 분위기의 뉴스룸에서 개발되어서 보편적인 웹 개발 업무를 빠르고 쉽게 만들어주도록 설계되었습니다. 여기서는 Django와 데이터 드리븐 웹 어플리케이션을 어떻게 작성하는지에 대한 개요를 보실수 있습니다.

이 문서의 목표는 Django가 어떻게 동작하는지 이해하는데 충분한 기술적 사항들을 알려주는데 있습니다. 하지만 튜토리얼이나 레퍼런스의 역할을 의도하지는 않습니다 -- 물론 우리는 그 두가지를 다 가지고있죠! 프로젝트를 시작할 준비가 되었으면 튜토리얼로 시작하거나 바로 좀더 자세한 문서로 뛰어들수 있습니다.

모델 설계

설사 Django를 데이터베이스 없이 쓸 수 있을 지라도 데이터베이스 레이아웃을 파이썬 코드로 표현할 수 있는 object-relational mapper가 같이 딸려 옵니다.

data-model 구문은 당신의 모델을 표현할 풍부한 방법을 제공해줍니다 -- 이는 지금까지 수년간 데이터베이스 스키마 문제들을 해결하는데에 많은 도움을 주어왔습니다. 아래의 간단한 예제를 보시죠.

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

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

    def __str__(self):
        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):
        return self.headline

설치하기

다음으로, 데이터베이스를 자동으로 생성해주는 Django command-line 유틸리티를 실행하여 줍니다:

$ python manage.py makemigrations
$ python manage.py migrate
...\> py manage.py makemigrations
...\> py manage.py migrate

makemigrations 명령은 생성 가능한 모델을 찾아 테이블이 존재하지 않을 경우 마이그레이션을 생성합니다. migrate 명령은 마이그레이션을 실행하고 사용자의 데이터베이스에 테이블을 생성합니다. 이는 더욱 풍부한 스키마 제어를 선택적으로 제공합니다.

자유로운 API 즐기기

With that, you've got a free, and rich, Python API to access your data. The API is created on the fly, no code generation necessary:

# Import the models we created from our "news" app
>>> from news.models import Article, Reporter

# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>

# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')

# Save the object into the database. You have to call save() explicitly.
>>> r.save()

# Now it has an ID.
>>> r.id
1

# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'

# Django provides a rich database lookup API.
>>> 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.

# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'

# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()

# Delete an object with delete().
>>> r.delete()

동적인 관리자 인터페이스: 단순한 뼈대 세우기가 아닙니다 -- 이것은 완성된 집입니다

Once your models are defined, Django can automatically create a professional, production ready administrative interface -- a website that lets authenticated users add, change and delete objects. The only step required is to register your model in the admin site:

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)

The philosophy here is that your site is edited by a staff, or a client, or maybe just you -- and you don't want to have to deal with creating backend interfaces only to manage content.

Django 앱을 생성하는 하나의 전형적인 작업 흐름은 일단 모델을 만들고 관리자 사이트를 올려서 가능한 빨리 작동할 수 있게 만드는 것입니다, 그래서 당신의 운영자(혹은 고객)이 데이터 입력을 시작할 수 있게 합니다. 그러면 밖으로 데이터를 표현하는 방법을 개발합니다.

URL 설계

깔끔하고 우아한 URL 계획은 고품질의 웹 어플리케이션에 매우 중요한 부분입니다. Django는 아름다운 URL 설계를 장려하며 URL에 .php.asp 같은 불필요한 내용들을 넣지 않습니다.

To design URLs for an app, you create a Python module called a URLconf. A table of contents for your app, it contains a mapping between URL patterns and Python callback functions. URLconfs also serve to decouple URLs from Python code.

아래의 코드는 위의 Reporter/Article 예제에 대해서 URLconf를 어떻게 쓰는지 보여줍니다:

mysite/news/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]

위 코드는 URL 경로들을 파이썬 콜백 함수들("views")로 연결해 줍니다. 경로를 나타내는 문자열들은 매개 변수 태그들을 사용하여 URL 로부터 값을 "캡처"합니다. 사용자가 페이지를 요청하면, Django 는 각 경로를 순서대로 실행하고, 요청된 URL 과 일치하는 첫번째 것에서 정지하게 됩니다. (만약 아무것도 매치하는 것이 없다면, Django 는 특수한 사례인 404 view 를 호출합니다.) 이 경로들은 로드할 때 정규표현식으로 컴파일 되어 있기 때문에 엄청나게 빠릅니다.

URL 패턴 중 하나가 일치하면 Django는 주어진 뷰를 호출합니다. 뷰는 파이썬 함수로, 각각의 뷰에는 요청 메타데이터가 포함된 요청 개체와 패턴에 잡힌 값이 전달 됩니다.

예를 들어, 사용자가 URL "/articles/2005/05/39323/"로 요청을 보냅니다, 그러면 Django는 다음처럼 함수를 호출하게 됩니다. news.views.article_detail(request, year=2005, month=5, pk=39323).

뷰 작성하기

각각의 뷰는 다음 두 가지 중 하나를 수행할 책임이 있습니다. 요청된 페이지의 내용을 담고 있는 HttpResponse 객체를 반환하거나, 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)

이 예제는 Django의 템플릿 시스템을 사용합니다. Django 템플릿 시스템은 몇몇 강력한 기능들을 가지고 있지만 프로그래머가 아닌 사람도 사용하기에 어렵지 않도록 간결함을 유지하도록 노력하였습니다.

여러분만의 템플릿 작성

위의 코드는 news/year_archive.html 템플릿을 로드합니다.

장고는 여러분이 템플릿들중 중복을 최소화할 수 있게 하는 템플릿 검색 경로를 가지고 있습니다. 여러분의 장소 셋팅에 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" }}는 유닉스 스타일의 “파이프”(“|” 문자)를 사용한것입니다. 이 파이프는 템플릿 필터를 호출하며 이를 통해 변수의 값을 필터링 할 수 있습니다. 이 코드에서 date 필터는 파이썬의 datetime 개체를 지정한 포맷으로 변환 시킵니다.(PHP의 date 함수처럼 말이죠, 네 PHP 의 좋은 아이디어 중에 하나입니다.)

여러분은 좋아하는 여러 필터들을 함께 연결할 수 있습니다. 여러분은 커스텀 템플릿 필터를 작성할 수 있습니다. 여러분은 은밀하게 실행되는 커스텀 파이썬 코드인 커스텀 템플릿 태그를 작성할 수도 있습니다.

이제 마지막으로 Django의 “템플릿 상속” 개념을 사용해 보죠. 이를 통해 {% extends "base.html" %} 코드가 무슨 일을 하는지 알 수 있습니다. 이 코드의 의미는 ”한 뭉치의 block들이 정의된 ‘base’라는 템플릿을 먼저 로드하고 뒤따르는 block들로 이 block들을 채운다는것”입니다. 간단히 말해 템플릿 안의 중복을 극적으로 낮추게 합니다. 각각의 템플릿은 자신이 표현하려는 내용들만 정의할 수 있게 되기 때문입니다.

“base.html” 템플릿은 정적 파일의 사용을 포함하여, 다음과 같이 보일 것입니다.

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>

Simplistically, it defines the look-and-feel of the site (with the site's logo), and provides "holes" for child templates to fill. This means that a site redesign can be done by changing a single file -- the base template.

It also lets you create multiple versions of a site, with different base templates, while reusing child templates. Django's creators have used this technique to create strikingly different mobile versions of sites by only creating a new base template.

여러분이 선호하는 템플릿 시스템이 있다면 꼭 Django의 템플릿 시스템을 사용할 필요는 없습니다. Django의 템플릿 시스템은 Django의 모델계층과 매우 잘 통합되어 있지만 꼭 이를 사용하도록 강제하는 것은 아닙니다. 이러한 이유들로 Django의 데이터베이스 API 역시 반드시 써야 할 필요는 없습니다. 여러분은 다른 데이터베이스 추상화 계층을 사용할수 있으며 XML 파일이나 디스크에서 다른 파일을 사용하거나 여러분이 원하는 다른 여러가지 방식으로 사용할수도 있습니다. 각각의 Django 구성요소들 -- 모델, 뷰, 템플릿 -- 은 서로 결합도가 낮게 되어있습니다.

이건 단지 껍데기일 뿐

이건 Django의 기능에 대한 간략한 개요에 불과합니다. 다음과 같이 좀 더 유용한 기능들도 많습니다.

  • memached나 기타 백엔드와 통합된 캐시 프레임워크.
  • A syndication framework that lets you create RSS and Atom feeds by writing a small Python class.
  • 이보다 더 매력적인 자동생성 관리자 기능 -- 이 개요는 극히 일부만 다루었습니다.

The next steps are for you to download Django, read the tutorial and join the community. Thanks for your interest!

Back to Top