첫번째 Django 앱 만들기! part 2

본 자습서는 Tutorial 1 에 이어 계속됩니다. 앞서 개발한 설문조사 애플리케이션과 함께 Django 에서 자동으로 생성되는 관리자 사이트에 대해 알아보도록 하겠습니다.

철학

관리자나 고객들이 컨텐츠를 추가, 변경, 삭제할 수 있는 관리자 사이트를 생성하는 것은 그다지 창조적이지 않은 지루한 작업 입니다. 이러한 작업을 위해서 Django 는 모델을 위한 관리자 인터페이스 생성을 완전히 자동화 하였습니다.

Django 는 뉴스를 준비하는 환경을 위해 만들어졌으며, “컨텐츠 발행인”과 “공개” 사이트를 완벽히 분리하였습니다. 사이트 관리자들은 새로운 스토리나 이벤트, 스포츠 점수 결과 등을 추가하기 위해 시스템을 이용하며, 이런 컨텐츠들은 공개 사이트에 노출됩니다. Django 는 사이트 관리자들이 컨텐츠를 수정할 수 있는 통합 인터페이스를 제공함으로서 문제를 해결합니다.

관리자 사이트는 사이트 방문자를 위한 것이 아닙니다. 이는 관리자들을 위한 것 입니다.

관리자 사이트 활성화 하기

관리자 사이트는 디폴트로 활성화 되지 않습니다. – 선택사항 입니다. 관리자 사이트를 활성화 시키기 위해 다음 세 가지의 작업이 필요합니다:

  • INSTALLED_APPS 설정에 있는 "django.contrib.admin" 의 주석을 제거하세요.

  • python manage.py syncdb 명령어를 실행하세요. 여러분이 INSTALLED_APPS 에 새로운 어플리케이션을 설치하였기 때문에 데이터베이스 테이블을 업데이트 해야 합니다.

  • mysite/urls.py 파일을 열어 관리 사이트와 관련된 행의 주석을 제거하세요 – 총 세 개 행의 주석을 제거해야 합니다. 이 파일은 URL 설정(URLconf) 파일이며 다음 자습서에서 보다 자세히 알아보겠습니다. 지금 여러분이 알아야 할 부분은 URL roots 를 어플리케이션에 연결시키는 것 입니다. 연결 후 여러분은 아래와 같은 urls.py 파일을 확인하실 수 있습니다.

    from django.conf.urls import patterns, include, url
    
    # 관리자 사이트를 활성화 시키기 위해 다음 두 줄의 주석을 제거 해 주세요.:
    from django.contrib import admin
    admin.autodiscover()
    
    urlpatterns = patterns('',
        # 예제:
        # url(r'^$', '{{ project_name }}.views.home', name='home'),
        # url(r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')),
    
        # 관리자 사이트 문서를 활성화 시키기 위해 admin/doc 의 주석을 제거 해 주세요.:
        # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    
        # 관리자 사이트를 활성화 시키기 위해 다음 줄의 주석을 제거 해 주세요.:
        url(r'^admin/', include(admin.site.urls)),
    )
    

    (굵게 표시된 행이 주석이 제거된 행입니다.)

개발 서버 실행하기

이제 개발 서버를 실행 시키고 본격적으로 관리자 사이트를 탐험해 보도록 하겠습니다.

첫 번째 자습서에서 배운 내용을 참고하여 아래와 같이 개발 서버를 실행 해 보세요.

python manage.py runserver

이제 웹 브라우저를 실행하고 로컬 도메인의 “/admin/” 으로 이동하세요 – 예: http://127.0.0.1:8000/admin/. 관리자 사이트의 로그인 화면을 볼 수 있을 것 입니다.

Django 관리자 사이트 로그인 화면

여러분에게 보이는 페이지와 다른가요?

만약 위에서 보이는 로그인 페이지 대신에 아래와 같은 error page reporting이 보인다면:

ImportError at /admin/
cannot import name patterns
...

여러분이 사용하시는 Django 의 버젼이 본 자습서의 버젼과 맞지 않을 수 있습니다. 사용하시는 Django 버젼에 맞는 자습서를 참고 하거나, 새로운 버젼의 Django 를 사용하시기 바랍니다.

관리자 사이트 들어가기

자, 이제 로그인 해 보세요. (첫번째 자습서에서 최고 관리자 계정을 생성한 것을 기억 하시나요? 만약 생성하지 않았거나, 비밀번호가 기억나지 않는다면 다른 계정을 생성 해 보세요.) 장고 관리자 사이트의 첫 페이지를 확인할 수 있을 것 입니다.

Django 관리자 사이트 첫 페이지

Groups, users, sites 등 몇 개의 수정 가능한 컨텐츠를 확인할 수 있는데, 이들은 Django 에서 기본적으로 제공하는 핵심 기능 입니다.

관리자 사이트에서 수정 가능한 설문조사 앱 만들기

그러데 우리의 설문조사 앱은 어디에 있나요? 아직 관리자 사이트 첫 페이지에 보이지 않습니다.

단 한가지 할 일: 우선 관리자 사이트에게 Poll 개체가 관리자 인터페이스가 필요하다고 알려줘야 합니다. 이를 위해 polls 디렉토리 안에 admin.py 파일을 생성하고 아래와 같이 수정합니다.

from polls.models import Poll
from django.contrib import admin

admin.site.register(Poll)

수정사항을 확인하기 위해 개발 서버를 재시작해야 합니다. 일반적으로 파일이 수정되면 서버는 자동으로 수정된 코드를 다시 불러오지만 새로 생성된 파일은 자동으로 불러오지 않습니다.

무료 관리 기능 탐험하기

자, 이제 Poll 이 등록되었고, Django 는 Poll 을 관리 사이트 첫 페이지에 보여줘야 함을 알고 있습니다.

polls가 보여지는 Django 관리자 사이트 첫 페이지

이제 “Polls”를 클릭하면 polls의 “change list” 를 볼 수 있습니다. 이 페이지에서는 데이터베이스의 모든 poll이 보여지게 되며 이중 한개를 선택하여 변경할 수 있습니다. 여기에 우리가 첫 번째 자습서에서 생성한 “What’s up?” poll을 확인할 수 있습니다.

Poll 변경 리스트 페이지

Poll을 수정하기 위해 “What’s up?” poll을 클릭하세요.

Poll 개체 수정 폼

여기서 짚고 넘어가기:

  • 폼은 Poll 모델로부터 자동적으로 생성되었습니다.
  • 서로 다른 모델의 필드 타입 (DateTimeField, CharField) 에 따라 적절한 HTML 입력 위젯이 보여집니다. 각각의 필드는 장고의 관리자 사이트에서 어떻게 보여질지 스스로 알고 있습니다.
  • 각각의 DateTimeField 에는 간편한 JavaScript 기능이 제공됩니다. 날짜는 “Today” 바로입력과 달력 팝업이 제공되며, 시간에는 “Now” 바로입력과 일반적으로 시간 입력에 사용되는 간편한 팝업이 제공됩니다.

페이지 하단에는 몇가지 옵션이 제공됩니다.

  • Save – 변경사항을 저장하고 현재 개체 타입의 변경된 목록 페이지를 보여줍니다.
  • Save and continue editing – 변경사항을 저장하고 현 개체의 관리 페이지를 다시 보여줍니다.
  • Save and add another – 변경사항을 저장하고 현재 개체 타입의 신규 정보를 등록할 수 있는 비어있는 폼을 보여줍니다.
  • Delete – 삭제 확인 페이지를 보여줍니다.

만약 “Date published” 의 시간이 여러분이 자습서 1에서 poll을 생성한 시간과 맞지 않는다면 정확한 TIME_ZONE 설정하지 않았기 때문 일 수 있습니다. 값을 정확히 입력하고 페이지를 다시 읽어들이면 정확한 값이 보여지는 것을 확인할 수 있을 것입니다.

“Today” 와 “Now” 바로입력 버튼을 누르면 “Date published”의 정보를 바꿀 수 있습니다. 그리고 “Save and continue editing.” 를 클릭한 후 오른쪽 위의 “History” 를 클릭 해 보세요. 이 페이지 에서는 Django 관리 사이트에서 이루어진 현 개체의 모든 변경 사항의 목록을 확인할 수 있으며, 수정 시간과 수정을 한 사용자 이름도 확인할 수 있습니다.

Poll 개체의 History 페이지

관리자 사이트 폼 커스터마이즈 하기

몇분 동안 간단히 코드를 살펴보며 감탄한 것 처럼 여러분은 코드를 작성 할 필요가 없습니다. 단지 Poll 모델과 admin.site.register(Poll) 을 등록 하는 것 만으로, Django는 기본적인 폼의 외형을 생성할 수 있었습니다. 때때로 여러분은 관리자 사이트 폼의 외형과 작업을 커스터마이즈 해야 할 필요가 있을 것 입니다. 이는 여러분이 개채를 등록할 때 필요한 옵션을 Django 에게 알려주면 됩니다..

수정 폼의 필드를 재 정렬 하는 예제를 통해서 어떻게 커스터마이즈 할 수 있는지 알아봅시다. admin.site.register(Poll) 라인을 아래와 같이 수정 해 봅시다.

class PollAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question']

admin.site.register(Poll, PollAdmin)

여러분은 위와 같은 패턴 – Model admin 개체 생성, admin.site.register() 의 두번째 인자로 전달 – 을 통해 언제든 개체의 관리 사이트 옵션을 변경할 수 있습니다.

이번 예제는 “Publication date” 필드가 “Question” 필드의 앞에 오도록 수정하였습니다.

재 정렬된 필드들

단지 두 개의 필드에서는 크게 인상적이지 않을 지 모르지만 수십개의 필드가 있는 폼에서는 직관적인 순서를 선택하는 것이 보다 세세한 사용성 측면에서 중요합니다.

또한 수십개의 필드를 포함한 폼을 다룰 때에는 이들을 폼의 필드셋(fieldsets)으로 분리할 수도 있습니다.

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Poll, PollAdmin)

필드셋의 튜플(tuple)에 있는 각각의 첫 번째 요소는 필드셋의 제목을 의미합니다. 아래에서 우리가 만든 폼이 어떻게 보이는지 확인할 수 있습니다.

필드셋을 보여주는 폼

각각의 필드셋에는 여러분이 원하는 HTML 클래스를 할당할 수 있습니다. Django 는 특정 필드셋이 처음에 접혀 있는 모습으로 보여질 수 있도록``”collapse”`` 클래스를 제공합니다. 이는 잘 사용하지 않지만 많은 필드를 가지고 있는 길이가 긴 폼이 있을 때 유용할 것입니다.

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
처음에 접혀있는 필드셋

관계가 있는 개체 추가

자 이제 우리는 Poll 관리자 페이지를 가지게 됐습니다. 그런데 Poll 은 여러개의 Choices 를 포함하고 있는데 관리자 페이지는 Choices를 보여주지 않습니다.

아직까지는요.

두 가지 방법을 통해 이 문제를 해결할 수 있습니다. 첫 번째 방법은 관리자 페이지에 Poll 과 함께 Choice 를 등록하는 것 입니다. 참 쉽죠?

from polls.models import Choice

admin.site.register(Choice)

자, 이제 Django 관리자 페이지에서 “Choices” 옵션을 사용가능한것을 볼 수 있습니다. 자 이제 아래와 같은 “Add choice” 을 확인할 수 있습니다.

Choice 의 관리 페이지

폼 안에서 “Poll” 필드는 선택 박스(Select Box)로서 데이터베이스의 모든 Poll을 포함하고 있습니다. Django 장고는 ForeignKey 가 관리 페이지에서 <select> 박스로 보여져야 한다는 것을 알고 있습니다. 현재 예제 에서는 한개의 Poll만 존재하는 상태 입니다.

“Poll” 다음에 있는 “Add Another” 링크에 주목하세요. 다른 개체에 대한 ForeignKey 관계를 가지고 있는 모든 개체는 손쉽게 이용할 수 있습니다. “Add Another” 를 클릭하면 “Add poll” 폼이 있는 팝업 윈도우를 볼 수 있습니다. 팝업 윈도우에서 Poll을 추가 하고 “Save” 버튼을 누르면 Django 는 Poll을 데이터베이스에 저장하고 여러분이 보고있는 “Add choice”의 선택된 Choice에 동적으로 추가합니다.

그러나 시스템에 Choice 개체를 추가하는 작업은 비효율적인 작업입니다. 만약 여러분이 Poll 개체를 만들 때 여러개의 Choice를 추가할 수 있다면 더 좋을 것 입니다. 자, 그럼 어떻게 하는지 알아봅시다.

Choice 모델을 호출하는 register() 를 제거하세요. 그런 다음 Poll 을 불러오기 위해 등록 코드를 수정하세요.

class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Poll, PollAdmin)

이런 작업은 Django에게 “Choice 개체들이 Poll 관리자 페이지에서 수정됨” 을 알려줍니다. 기본적으로 3개의 충분한 Choice 필드를 제공합니다.”

“Add poll” 페이지를 열어 어떻게 보이는지 확인 해 봅시다. 그 전에 개발 서버를 재시작 해 주세요.

Choice 가 포함된 Poll 페이지

이렇게 작동합니다.: 관련된 세개의 슬롯 – extra 에 의해 선택된 – 이 있고 언제든지 생성된 개체의 “수정” 페이지로 되돌아올 수 있으며, 또다른 세개의 추가 슬롯을 사용할 수도 있다.

한 가지 작은 문제에 대해 생각 해 봅시다. 관련된 Choice 개체를 입력하기 위해 모든 필드가 넓은 공간에 보여지고 있습니다. 이러한 이유로 Django 는 표를 이용하여 연관된 개체를 한 줄로 보여줍니다.; 다른과 같이 ChoiceInline 를 변경하세요.

class ChoiceInline(admin.TabularInline):
    #...

StackedInline 대신에 TabularInline 을 사용하면 연관된 개체는 보다 간소화된 표 기반 형식으로 표현됩니다.

보다 간소화된 Choice를 포함한 Poll 추가 페이지

관리자 페이지의 수정 목록 커스터마이즈

이제 Poll 관리 페이지가 보기 좋아졌습니다. 다음으로 시스템의 모든 Poll을 보여주는 “변깅 리스트(change list)” 페이지를 수정 해 봅시다.

현재는 아래와 같이 보입니다.:

Poll 변경 리스트 페이지

기본적으로 Django 는 각 개체를 str() 로 보여줍니다. 그러나 각 필드를 직접 보여주는 것이 더 효과적일 수도 있습니다. 이를 위해 list_display 관리 옵션을 사용합니다. list_display 옵션은 개체의 변경 리스트에서 컬럼 이름으로 사용되는 필드 이름의 튜플로 구성됩니다.

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date')

좋은 지표로 삼기 위해 첫번째 자습서에서 만든 커스텀 메소드인 was_published_recently 을 포함시켜 봅시다.

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date', 'was_published_recently')

이제 아래와 같은 Poll 변경 리스트를 확인하실 수 있습니다.

업데이트 된 Poll 변경 리스트 페이지

컬럼 값에 따라 정렬하기 위해 컬럼 헤더를 클릭해 보세요. – 커스텀 메소드인 was_published_recently 는 정렬을 지원하지 않습니다. was_published_recently 의 컬럼 해더는 기본적으로 메소드의 이름으로 포현되며(공백은 밑줄로 대체) 각 컬럼은 문자열로 표현되게 됩니다.

여러분은 아래와 같이 models.py 에 있는 몇 개의 어트리뷰트를 변경하여 보다 보기 좋게 만들 수 있습니다.

class Poll(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

admin.py 파일을 수정하여 Poll 수정 리스트를 향상시킬 수 있습니다.: 필터. PollAdmin 에 아래 코드를 추가하세요.:

list_filter = ['pub_date']

사이드 바에 추가된 “Filter” 되어 사용자 들이 수정 목록을 pub_date 필드로 필터링 할 수 있습니다.:

업데이트 된 Poll 변경 리스트 페이지

여러분이 필터링 하는 필드의 타입에 따라 필터의 타입이 보여지게 됩니다. pub_dateDateTimeField 이기 때문에 Django 는 적절한 옵션을 제공합니다.: “Any date,” “Today,” “Past 7 days,” “This month,” “This year.”

꽤 사용하기 편하게 구성되죠?이제 검색 기능을 추가 해 봅시다.

search_fields = ['question']

위의 옵션은 수정 목록 상단에 검색창(Search Box)를 추가합니다. 사용자가 검색어를 입력하면 Django 는 question 필드를 검색합니다. 여러분은 여러분이 원하는 만큼 필드를 추가할 수 있으며 내부에서 LIKE 질의를 하기 때문에 데이터베이스의 효율을 높일 수 있습니다.

마지막으로 Poll 개체는 날짜를 포함하므로 손쉽게 날짜 순으로 보여줄 수 있습니다. 아래 코드를 추가하세요.

date_hierarchy = 'pub_date'

이는 수정 목록 페이지의 상단에서 날짜 순의 계층적 탐색을 추가합니다. 최상위 수준에서 선택 가능한 모든 연도가 표시됩니다. 또한 월 에서 일까지 순차적으로 선택할 수 있습니다.

이제 수정 리스트의 페이지네이션에 대하여 알아봅시다. 기본적으로 한 페이지에 100개의 아이템이 보여집니다. 이제 수정 목록 페이지네이션(Change-list pagination), 검색창(search boxes), 필터(filters), 날짜 구조화(date-hierarchies) and 컬럼 헤더 정렬(column-header-ordering) 모두 여러분이 생각하는 대로 작동합니다.

관리자 사이트 룩앤필(Look and feel) 커스터마이즈 하기

모든 관리자 페이지의 최상단에 존재하는 “Django administration” 가 조금은 이상하게 느껴집니다. 이는 임시적인 문구 입니다.

Django 의 템플릿 시스템을 이용하면 쉽게 변경할 수 있습니다. Django 관리자 사이트는 Django 기반으로 개발되었기 때문에 Django의 자체 템플릿 시스템을 사용하여 인터페이스를 제공하고 있습니다.

설정 파일(mysite/settings.py, 기억하나요?)을 열어 TEMPLATE_DIRS 설정을 봅시다. TEMPLATE_DIRS 은 Django 템플릿을 불러올 때 확인하는 파일 시스템 디렉토리로 구성된 튜플로 구성됩니다. 이는 검색을 위한 패스 입니다.

기본적으로 TEMPLATE_DIRS 는 비어있습니다. 이제 Django에게 어디에 우리의 템플릿이 있는지 알려주기 위해 한 줄 추가 해 봅시다.

TEMPLATE_DIRS = (
    '/home/my_username/mytemplates', # 여러분의 디렉토리로 변경 해 주세요.
)

이제 Django 소스코드의 기본 Django 관리자 템플릿 디렉토리 (django/contrib/admin/templates) 에 있는 admin/base_site.html``를 여러분이 :setting:`TEMPLATE_DIRS`에 지정한 디렉토리의 ``admin 하위 디렉토리로 복사합니다. 예를 들어, 만약 여러분의 TEMPLATE_DIRS 에 위와 같이 '/home/my_username/mytemplates' 가 포함되어 있다면, django/contrib/admin/templates/admin/base_site.html/home/my_username/mytemplates/admin/base_site.html 로 복사하세요. admin 의 하위 디렉토리를 잊지 마세요.

다음으로, 파일을 수정하여 이미 입력 되어 있는 Django 텍스트를 적절한 여러분의 사이트 이름으로 교체해 주세요.

이 템플릿 파일은 여러개의 {% block branding %}{{ title }} 을 포함하고 있습니다. {%{{ 는 Django 템플릿 언어 중 일부입니다. Django 가 admin/base_site.html 를 출력할 때 HTML 페이지를 완성하기 위하여 이 텀플릿 언어는 평가됩니다. 여러분이 지금 템플릿에 대해 잘 알지 못해도 걱정하지 마세요. 세번째 자습서에서 Django의 탐플릿 언어에 대해 자세히 알아볼 것 입니다.

Django의 기본 관리자 사이트 템플릿은 재정의(Override) 될 수 있다는 것만 알아두세요. 템플릿을 재정의 하기 위해, 위에서 한 작업들을 base_site.html 에 해 주세요. – 파일을 기본 디렉토리에서 여러분의 커스텀 디렉토리에 복사한 후 수정하세요.

여기서 날카로운 여러분은 의문이 생길겁니다.: 만약 기본적으로 TEMPLATE_DIRS 가 비어있다면, Django는 어떻게 기본 관리자 사이트 템플릿을 찾나요? 정답은, Django는 기본적으로 각 앱 패키지의 하위 디렉토리에 있는 templates/ 의 템플릿을 자동으로 대체하여 사용합니다. 보다 자세한 정보를 위해 template loader documentation 을 참조하세요.

관리자 사이트 첫 페이지 커스터마이즈 하기

여러분은 이제 Django 관리 사이트의 첫 페이지 룩앤필도 커스터마이즈하고 싶을 것입니다.

기본적으로 첫 페이지는 INSTALLED_APPS 에 등록된 모든 앱을 알파벳 순서로 보여줍니다. 여러분은 아마 레이아웃을 여러분이 원하는데로 변경하고 싶을 것 입니다. 초기 페이지는 관리자 사이트에서 가장 중요한 페이지 이며 쉽게 사용할 수 있어야 합니다.

초기 페이지의 커스터마이즈 템플릿은 admin/index.html 파일 입니다. (이 전 섹션에서 admin/base_site.html 에서 한 작업들을 그대로 해 주세요. – 파일을 기본 디렉토리에서 여러분의 커스텀 디렉토리에 복사 한 후 수정하세요.) 파일을 수정 할 때 app_list 변수를 확인할 수 있을 것 입니다. 변수는 여러분이 설치한 모든 Django 앱이 포함되어 있을 것 입니다. 이 링크를 그대로 사용해도 되지만, 어려분이 생각하는 데로 관리자 페이지의 개체에 링크를 직접 연결할 수도 있습니다. 다시 한번 얘기 드리지만, 템플릿 언어를 모른다고 걱정하지 마세요. – 세 번째 자습서에서 보다 자세히 알아볼 것 입니다.

이제 관리자 사이트에 익숙해졌다면, 세 번째 자습서를 통해 공개된 poll 뷰에 대해 알아봅시다.