3. 튜토리얼 따라하기 - 설문조사 - 1

2019. 5. 24. 21:10파이썬 웹프로그래밍

천리길도 한걸음 부터라고 했습니다. 이번 장에서는 장고 공식 튜토리얼을 따라하면서 사이트를 만드는 과정을 체험해보고 장고로 어떻게 웹 어플리케이션을 만드는지 순서를 익혀보겠습니다.

3. 설문조사 서비스 만들기

설문조사 서비스는 장고의 공식 튜토리얼입니다. 따라서 자세한 내용을 살펴보기보다 전테 제작 흐름과 튜토리얼에서 알려주고자 하는 바를 살펴보는 방식으로 가볍게 진행하겠습니다.

3.1. 프로젝트 만들기

파이참을 켜고  웰컴 창에서 [Create New Project] 버튼을 클릭해 새로운 프로젝트를 만듭니다.

프로젝트의 이름을 설정하고, 가상환경도 같이 만들어 줍니다. [Create] 버튼을 클릭합니다.

프로그램을 만들고 나면 바로 장고를 설치합니다.

pip install django

장고를 설치하고 장고 프로젝트를 만듭니다.

django-admin startproject config .

프로젝트를 만들고 나면 관련 파일들을 확인할 수 있습니다.

3.2. 웹 서버 시작하기

웹 서버를 실행해 서비스를 확인해 보겠습니다.

python manage.py runserver

웹 서버를 실행하면 메시지를 확인할 수 있습니다. 아래의 그림처럼 migration관련 경고 메시지가 나타납니다. 지금은 무시해도 괜찮습니다. 방금 실행한 웹 서버는 테스트 용도입니다. 실제 서비스를 사용할 때는 절대 이 웹 서버를 사용해서는 안됩니다. 다음 장부터 배포를 해볼텐데 그때부터는 wsgi를 사용해서 웹 서비스를 동작시킬 것입니다.

웹 서버를 실행하는 명령어의 옵션을 살펴 봅시다. 기본 웹 서버는 8000 포트를 기본으로 동작합니다. 포트를 변경하고 싶다면 포트 번호를 인수로 전달 합니다.

python manage.py 8000

만약 IP를 직접 지정하거나 같은 네트워크 망 안에서 접속이 가능 하도록 하고 싶다면 다음 명령어를 입력할 수 있습니다.

python manage.py 0.0.0.0:8000

혹은

python manage.py 0:8000

이 명령어에서 IP주소 0은 0.0.0.0의 약어입니다. 해당 형태로 동작 시킬 때는 settings.py에 있는 ALLOWED_HOSTS를 설정해야 합니다.

이 경량 웹 서버를 이용해 실제 서버에 배포하지 않아도 우리는 웹 서비스의 변경 사항을 테스트 해볼 수 있습니다. 또 서버가 실행 중이어도 소스 코드의 변경 사항은 자동으로 반영되기 때문에 소스 코드를 변경할 때마가 서버를 종료했다 다시 실행할 칠요가 없습니다.

웹 서버를 종료하고 싶을 때는 [Ctrl+C]키를 누르면 됩니다. 다음 단계를 위해 서버를 종료 합니다.

3.3. 설문조사 앱 만들기

프로젝트를 만들고 서버 환경도 확인했으니 앱을 만들겠습니다.

python manage.py startapp polls

앱을 만들면 생기는 새로운 파일들을 확인 할 수 있습니다.

3.4. 첫 번째 뷰 만들기

polls/views.py 파일을 열고 코드를 입력 합니다.

from django.http import HttpRespose

def index(request):

    return HttpResponse("Hello, world. You`re at the polls index.")

뷰를 만들면 이 뷰를 호출하기 위한 URL이 있어야 합니다. URL 연결을 위해 polls 폴더에 urls.py 파일을 만들겠습니다.

프로젝트 탐색기에서 polls 폴더를 마우스 오른쪽 버튼으로 클릭하면 메뉴가 나타납니다. 이 메뉴에서 [New->Python File]을 선택합니다.

새 파이썬 파일 만들기 창이 나타나면 [Name]에 [urls] 라고 입력하고 [OK] 버큰을 클릭합니다.

파일을 만들었다면 아래 그림처럼 polls 폴더 아래에 위치하고 있습니다.

urls.py 파일에 다음 코드를 입력 합니다.

from django.urls import path

from . import views

urlpatterns = [

    path('', views.index, name='index'),

]

path 함수는 path(route, view, kwargs, name) 형태로 호출합니다. 총 4개의 인수를 받는다는 것을 알 수 있습니다.

route 주소를 의미
view route의 주소로 접근했을 때 호출할 뷰
kwargs 뷰에 전달할 값들
name route의 이름을 의미합니다. 이 이름을 가지고 원하는 곳에서 주소를 호출해 출력하거나 사용할 수 있습니다. polls 폴더에 있는 urls.py는 앱의 라우팅만 담당합니다. 프로젝트의 메인 urls.py 파일에서 연결을 해줘야 정상 동작합니다. config/urls.py 파일을 다음 코드처럼 수정 합니다.

from django.contrib import admin

from django.urls import path, include

urlpatterns=[

    path('polls/', include('polls.urls')),

    path('admin/', admin.site.urls),

]

include는 다른 urls.py 파일을 참조할 수 있도록 합니다. 만약 127.0.0.1:8000/polls/list/ 라는 주소로 접속하면 polls/까지는 일치하기 때문에 잘라내고 나머지 list/ 부분만 polls/urls.py에서 찾아보는 방식으로 동작합니다.

python manage.py runserver

명령을 입력해 서버를 실행하고 127.0.0.1:8000/polls/ 라는 주소로 접속해 봅시다. polls 앱의 첫화면을 볼 수 있습니다. 확인했다면 다음 단계로 넘어 갑시다.

3.5. 데이터베이스 만들기

config/settings.py를 열어서 76번째 줄을 살펴 봅시다. 데이터베이스 관련 설정이 있습니다. [ENDINE]은 어떤 종류의 데이터베이스를 사용할지 설정하는 부분입니다. 기본적으로 'django.db.backends.sqlite3','django.db.backends.postgresql','django.db.bakends.mysql','django.db.backends.oracle' 이렇게 4가지를 사용할 수 있고 다른 데이터베이스도 사용할 수 있습니다. 원하는 데이터베이스의 사용법은 장고 매뉴얼이나 해당 데이터베이스 매뉴얼에서 찾아볼 수 있습니다.

데이터베이스를 만들고 초기화 하기 위해 아래 명령을 입력합니다.

python manage.py migrate

명령이 잘 실행된 것은 아래 그림처럼 OK 메시지로 확인 할 수 있습니다.

보통은 데이터베이스 관련 설정이 끝난 직후에 실행합니다. 데이터베이스를 만들었으니 앱에서 사용할 모델을 작성하겠습니다.

3.6. 모델 만들기

장고에서 모델은 데이터베이스의 구조도입니다. 데이터베이스에 어떤 테이블을 만들고 어떤 컬럼을 갖게 할 것인지 결정합니다. 또 해당 컬럼의 제약 조건까지도 모델에서 결정합니다. 이 모델은 보통 models.py에 작성하고 클래스 형태입니다.

투표 앱을 위한 두 개의 모델을 만들어 보겠습니다.

polls/models.py 파일에 아래 코드를 입력합니다.

from django.db import models

class Question(models.Model):

    question_text=models.CharField(max_length=200)

    pub_date=models.DateTimeField('date published')

class Choice(models.Model):

    question=models.ForeignKey(Question, on_delete=models.CASCADE)

    choice_text=models.CharField(max_length=200)

    votes=models.IntegerField(default=0)

장고의 모델은 [models.Model]을 상속받아 만듭니다. 이 부모 클래스가 실제로 데이터베이스와 ORM을 이용해 동작하는 기능들을 가지고 있습니다.

각 클래스 변수들은 필드 값을 갖습니다. 해당 필드는 자료형과 같습니다. [CharField]는 문자열 타입이고 [DateTimeField]는 날짜와 시간 형태입니다. 다른 설정을 하지 않으면 각 변수명이 실제 데이터베이스와 장고가 사용하는 변수명입니다. 만약 사람이 읽기 쉬운 형태를 사용하고 싶다면 'date published'처럼 인자로 전달하면 됩니다. 제약 조건을 결정하고 싶다면 max_length=200처럼 인자로 전달합니다.

여기서 특이한 부분은 ForeignKwy입니다. 다른 모델과의 관계를 만들기 위해서 사용합니다. [Choice]모델이 ForeignKey로 [Choice] 모델이 [Question]에 소속된다는 것을 의미합니다.

모델을 완성했으니 데이터베이스에 적용해야 합니다. 이때 사용하는 명령이 migrate 명령들인데 이 명령을 사용하려면 polls 앱이 현재 프로젝트에 설치되어 있다고 알려줘야 합니다.

config/settings.py 파일을 열고 [INSTALLED_APPS] 변수 제일 윗줄에 polls 앱을 추가합니다.

INSTALLED_APPS=[

    'polls.apps.PollsConfig',

    'django.contrip.admin',

    'django.contrip.auth',

    'django.contrip.contenttypes',

    'django.contrip.sessions',

    'django.contrip.messages',

    'django.contrip.staticfiles',

'polls.apps.PollsConfig'는 polls 앱 폴더에 apps.py 파일에 있는 PollsConfig 클래스를 의미합니다. 짧게 쓰고 싶다면 [polls]라고 앱 이름만 써도 됩니다.

이제 데이터베이스에 적용해 봅시다.

python manage.py makemigrations polls

명령을 실행하면 앱의 변경사항을 추적해 데이터베이스에 적용할 내용을 만들어 냅니다. 그 결과는 polls/migrations/0001_initial.py 파일에 기록되어 있습니다.

이제 어떤 SQL 구문이 실행될지 확인해 봅시다.

python manage.py sqlmigrate polls 0001

명령을 입력하고 실행하면 여러줄의 SQL 구문이 나타납니다. 이것을 보고 어떤 SQL을 실행할지 또는 문제가 있는 쿼리는 아닐지 판단할 수 있습니다. 하지만 장고를 사용하면 ORM을 통해 이런 쿼리문을 잘 모르더라도 웹 서비스를 구축할 수 있습니다. 자세한 쿼리문에 대한 설명이 필요하시다면 각 데이터베이스의 매뉴얼을 참조하도록 합니다.

이렇게 두 명령을 실행해도 아직은 데이터베이스에 반영이 된 상태가 아닙니다. 변경사항을 데이터베이스에 반영하기 위한 명령을 입력하겠습니다.

python manage.py migrate polls 0001

이 명령을 실행하면 데이터베이스에 테이블을 생성하고 초기화 할 수 있습니다.

3.7. 모델에 함수 추가하기

polls/models.py의 [Question] 모델과 [Choice] 모델에 [__str__] 메서드를 추가 합니다. 해당 메서드는 관리자 화면이나 쉘에서 객체를 출력할 때 나타날 내용을 결정합니다.

from django.db import models

class Question(models.Model):

    #...

    def __str__(self):

        return self.question_text

class Choice(models.Model):

    #....

    def __str__(self):

        return self.choice_text

다른 메서드도 하나 추가해 보겠습니다. 다음 코드를 보고 [was_published_recently] 메서드를 추가하고 해당 메서드가 잘 동작하도록 datetime과 timezone도 import 합니다.

import datetime

from django.db import models

from django.utils import timezone

class Question(models.Model):

    #...

    def was_published_recently(self):

        return self.pub_date >= timezone.now() - datetime. timedelta(days=1)

모델을 작성한 후에 단순 메서드 변경은 migrate를 할 필요가 없습니다. 모델 작성을 끝냈으니 관리자 페이지에서 확인해 보겠습니다.