전체 페이지뷰

2016년 12월 7일 수요일

Blog 앱 만들기 1, 디자인과 모델 코딩

**장고걸스 튜토리얼, 장고 공식 튜토리얼, 김석훈 님의 저서 "파이썬 웹프로그래밍:실전편"을 토대로 자습 중입니다. **




어렴풋이 개발 과정이 눈에 들어오기 시작하는 듯도 합니다.
먼저 어떤 앱을 만들 것인가 결정을 하고 그에 따라 화면 UI를 설계합니다.
그 UI를 보여줄 테이블은 어떻게 구성될 것인가 디자인을 하고,
URL 구조를 설계합니다. 앞에 든 예는 간단하므로 URL이고 뭐고 별게 없었지만 지금부터는 조금 복잡하게 가야합니다. 그리고 실제 코딩 작업에 들어가서 뼈대를 만들고, 모델, URLconf, 뷰, 템플릿, 기타의 순으로 작성합니다.

이 순서대로 가 보겠습니다.

이번에 만들 앱은 blog입니다.
책과 여러 튜토리얼에서 기본적으로 구현해보고 있는 기본 중의 기본이죠.
그 중에서도 가장 간단한, 포스트의 리스트를 보여주고 클릭시 해당 글을 읽을 수 있는 형태로 가 보겠습니다.

어떤 것을 만들까 결정 했으니 화면에 어떤식으로 보여줄까 UI를 디자인 해 봐야겠죠.

먼저 post리스트를 보여줄 페이지입니다.(post_all.html로 구현될 것입니다.)
포스트의 제목과 포스트 수정일, 포스트 내용 간단설명으로 이루어지게 될 것입니다. 그리고 글이 많다면 화면 하단에 다음 목록으로 이동할 수 있는 버튼도 있어야 겠습니다.

그리고, 실제 포스트 제목을 클릭하면 보여질 post_detail.html입니다.
먼저 상단에 포스트 제목이 있어야겠죠. 그리고, 그 밑에 이전 글로 돌아갈수 있는 필드가 존재하고, 그 밑에 현재 글의 수정일, 글의 상세 내용이 나오게 될 것입니다.

UI에서 계획한 내용을 구현하기 위해서 필요한 테이블을 설계해 봅니다.
id: 기본 키
title: 포스트 제목
slug: 포스트 제목 별칭
description: 포스트 내용 한 줄 설명
content: 포스트 내용 기록
create_date: 포스트 생성일
modify_date: 포스트 수정일
(자세한 내용이 혹 궁금하신 분은 김석훈님의 파이썬 웹프로그래밍 실전편 64p참고)

이제 로직을 설계할 단계입니다.
각 개발대상에 필요한 로직을 설계하고 MTV간에 어떻게 배치할지를 고려합니다.
여기서는 admin과 북마크, 블로그의 단순 기능 밖에 없는 사이트이므로
바로 다음 단계인 URL 설계로 넘어갑니다.

각 페이지가 구현될 url이 어떻게 구성될지를 설계해봅니다.
/blog/ : PostLV(ListView) post_all.html
/blog/post/ : PostLV(ListView) post_all.html
/blog/post/dajngo-example/ : PostDV(DetailView) post_detail.html
/blog/archive/ : PostAV(ArchiveIndexView) post_archive.html
/blog/2012/ : PostYAV(YearArchiveView) post_archive_year.html
/blog/2012/nov/10/ : PostDAV(DayArchiveView) post_archive_day.html
/blg/today/ : PostTAV(TodayArchiveIndexView) post_archive_day.html
/admin/ : 장고제공기능
url을 설계하고 거기에 쓸 클래스형 뷰(상속받을 제너릭뷰)와 시각적으로 구현될 html을 정리해봅니다.

그 다음 실제 코딩 작업으로 들어갑니다.
코딩작업은
1.뼈대만들기: 이미 북마크 만드는 과정에서 구현했습니다. 블로그만 추가합니다.
2. 모델 코딩: models.py , admin.py, makemigration.py, migrate
3. URLconf: urls.py
4. 뷰 코딩: views.py
5. 템프릿 코딩: template 디렉토리
6. 기타 코딩
으 순으로 이루어집니다.

차례차례 해보겠습니다.

(myvenv) D:\myDjango>python manage.py startapp blog

으로 blog를 추가하고 bookmark 때와 같이 mysite의 settings.py를 열어 blog 관련사항을 추가합니다.
1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bookmark.apps.BookmarkConfig',
    'blog.apps.BlogConfig'  
]
cs

다음은 모델을 작성할 차례입니다.
(myvenv) D:\myDjango\blog>subl models.py
하여 models.py를 에디터에 띄우고 작성합니다.

from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models
from django.core.urlresolvers import reverse
# Create your models here.
@python_2_unicode_compatible
class Post(models.Model):
    title = models.CharField('TITLE',max_length=50)
    slug = models.SlugField('SLUG', unique=True, allow_unicode=True, help_text='one word for title alias.')
    description = models.CharField('DESCRIPTION', max_length=100, blank=True, help_text='simple description text')
    content = models.TextField('CONTENT')
    create_date = models.DateTimeField('Create Date', auto_now_add=True)
    modify_date = models.DateTimeField('Modify Date', auto_now=True)
    class Meta:
        verbose_name = 'post'
        verbose_name_plural = 'posts'
        db_table = 'my_post'
        ordering = ('-modify_date',)
    def __str__(self):
        return self.title
    def get_absolute_url(self):
        return reverse('blog:post_detail', args=(self.slug,))
    def get_previous_post(self):
        return self.get_previous_by_modify_date()
    def get_next_post(self):
        return self.get_next_by_modify_date()
cs

Django.core.urlresolvers로부터 reverse라는 함수를 임포트했습니다 (장고 2.0부터는 django.core.urlresolvers는 deprecated된다고 하며 django.urls로부터 임포트 해야 합니다. 일단은 책에 나온 대로 가보겠습니다). reverse()는 URL 패턴을 만들어주는 장고 내장함수입니다.

Post 클래스 내부에 컬럼으로 쓰일 변수들과 함수들을 정의합니다.

앞서 설계한대로 title,slug, description, content, create_date, modify_date를 각각의 필드에 맞춰 정의하고, 그 외에 필요한 파라미터가 있을 때 Meta클래스로 묶어 내부에 따로 정의해줍니다. 코드를 자세히 보기 전에 이 '필드'에 대해 자세히 짚어 보겠습니다.

이 필드라는 것은 추상 클래스인 'Field'의 파생 클래스들입니다.
Field의 옵션에 대해 알아보겠습니다.

null : null=True로 설정하면 데이터베이스에 NULL을 저장합니다(디폴트는 False).
CharField나 TextField에서는 사용하지 않아야 합니다(왜냐하면 빈 문자열은 ""이지 NULL이 아니기 때문).
blank : blank=True로 설정시 비워둘수 있습니다(디폴트는 False). null은 데이터베이스 저장에만 관련된 것이므로 null과 blank는 다릅니다.
choices : 튜플이나 리스트 같은 iterable을 클래스 내부에서 이 옵션과 함께 사용하면 위젯이 선택하는 창을 보여줍니다.
db_column : db에서의 컬럼 이름을 정해줍니다. 주어지지 않으면 그냥 장고 필드명이 사용됩니다.
db_index : True로 설정하면 index가 생성됩니다.
db_tablespace : 필드의 인덱스를 사용하기 위한 데이터베이스 tablespace 이름입니다.
default : 값이나 객체 모두 가능합니다(list나 set같은 mutable은 사용 불가합니다).
editable : False로 설정되면 Admin에 나타나지 않습니다(디폴트는 True).
error_messages : field가 일으킬수 있는 디폴트 에러메세지를 오버라이드 할수 있게 해 줍니다.
help_text : 폼 위젯에 나타나는 설명입니다.
primary_key : True로 설정시 이 필드는 모델의 primary key로 사용됩니다.
필드 내에 primary_key가 True로 된 것이 없으면 장고는 자동으로 AutoField를 생성합니다.
unique : true로 설정시 이 필드는 테이블 전체에서 unique해 집니다.
unique_for_date : DateField나 DateTimeField의 이름을 이 옵션으로 지정해주면 이 필드가 유니크해집니다.
unique_for_month : date의 경우와 동일
unique_for_year :
verbose_name : 사람이 알아보기 쉬운 긴 이름을 지어 가능합니다.
validators :

위와 같은 많은 옵션들이 기본으로 존재합니다. 이제 실제 코드를 살펴 보겠습니다.

title = models.CharField('TITLE', max_length=50)
포스트 제목 컬럼입니다.  짧은 길이의 string을 처리하며 (긴것은 TextField), max_length 인자로 최대 길이를 설정 가능합니다. 'TITLE'은 컬럼의 레이블로서 Admin에서 확인 가능합니다.

slug = models.SlugField('SLUG', unique=True, allow_unicode=True, help_text='one word for title alias')
단어와 숫자, 언더스코어 하이픈으로만 이루어진 짧은 라벨이라는 뜻의 신문용어입니다.
Unique 옵션을 주면 특정 포스트 검색시 기본 키 대신에 사용되며, allow_unicode로 한글 등에도 처리가 가능하게 합니다. help_text는 이 컬럼을 설명해주는 문구로서 폼 화면에 나타납니다.

description = models.CharField('DESCRIPTION', max_length=100, blank=True, help_text='simple description text')
포스트 내용 한줄 설명에 쓰이도록 설계했습니다. 길이는 100으로 주었고, 필요없을 경우 비워둘 수 있도록 blank=True로 두었습니다.

content = models.TextField('CONTENT')
TextField는 많은 양의 텍스트를 처리할 때 사용합니다. max_length로 길이를 제한할 수도 있지만 그럴 때는 차라리 CharField를 사용하는 것이 좋습니다.

create_date = models.DateTimeField('Create Date', auto_now_add=True)
필드명 그대로 날짜와 시간을 기록합니다. auto_now_add=True로 객체의 생성 시각을 자동 기록하게 해줍니다.

modify_date = models.DateTimeField('modify Date',auto_now=True)
auto_now는 객체가 DB에 저장될 때의 시각, 다시 말해 변경될 때의 시각을 자동 기록하게 합니다.

class Meta:
    verbose_name = 'post'
    verbose_name_plural = 'posts'
    db_table = 'my_post'
    ordering = ('-modify_date',)

필드 속성 외에 필요한 파라미터는 Meta 클래스로 묶어 줍니다.
테이블 별칭의 단수형을 'post'로, 복수형을 'posts'를 정해주고
데이터베이스에 저장되는 테이블의 이름을 my_post로 지정합니다(지정하지 않으면 디폴트로 '앱명_모델명'으로 정해집니다. 따라서 'blog-post'가 디폴트입니다).
모델 객체의 리스트 출력 순서를 modify_date기준 내림차순으로 정합니다.

__str__() 
객체의 타이틀을 반환해주는 함수입니다.

get_absolute_method()
내장함수인 reverse()를 사용하여 이 메소드가 정의된 객체를 지칭하는 URL을 반환합니다.

get_previous_post()
내장함수인 get_previous_by_modify_date()를 사용해서 modify_date 컬럼 기준으로 이전 포스트를 반환합니다.

get_next_post()
내장함수인 get_next_by_modify_date()를 이용해서 다음 포스트를 반환합니다.

다음 편엔 이어서 모델 코딩의 일부인 admin.py 작성과 데이터베이스 반영에 대해 공부하겠습니다.

댓글 없음:

댓글 쓰기