본문 바로가기

IT/Python

파이썬 장고(Django) - MTV 패턴을 통한 웹서버 개발하기

/* 
written by kaspy (kaspyx@gmail.com)
*/ 


번 포스팅에 이어서 이번에는 장고(Django)를 이용해서 웹페이지를 추가하고 이에대한 요청을 처리하는 웹페이지를 만드는 과정을 다루어보도록하겠습니다.


구현된 소스코드에는 자세히 다루지는 않겠지만 따라하기만 해도 어느정도 이해하는데 도움이 될것으로 생각합니다. 


개발 환경은 Ubuntu Linux 16.04 기준


1. 기본 프로젝트 및 구조 생성하기


우선 장고를 사용한 웹서버 구축하기를 먼저보고 오는게 좋을것이다. - link


1) 프로젝트 생성


 웹서버라면 제공하는 서비스에따라 다양한 요청을 처리할수있어야한다. 우선 프로젝트를 추가하고 어플리케이션을 추가하도록 하겠다.


이번 포스팅에서는 설문조사를 하는 사이트를 만들어보도록 하겠다.


아래 명령어를 실행하여 프로젝트를 만들어준다.


django-admin startproject mysite


2) 어플리케이션 생성


생성한 프로젝트로 경로를 옮긴다음에 app을 추가해주도록하자. 

(polls 라는 어플리케이션을 추가)


cd mysite

python manage.py startapp polls


3) 데이터 베이스 변경사항 반영


아래는 데이터베이스 변경사항이 있을때 이를 반영해주는 명령어입니다.


cd mysite

python manage.py migrate 

 

지금까지 한 작업이 잘 반영되어있는지 아래 명령어로 확인할수있음. (이전 포스팅에도 나와있음)


python manage.py runserver 0.0.0.0:8000



관리자 아이디 추가하기


cd mysite

python manage.py createsuperuser 


웹사이트가 만들어졌으니 위의 명령어로 관리자 아이디를 추가해야한다.


이제 프로젝트가 만들어졌을텐데 구조는 아래와같은 구조로 되어있을것이다.



2. MTV 패턴으로 웹페이지 개발하기


 장고(Django)는 기본적으로 MVC(Model View Controller) 패턴기반 MTV 개발을 지원한다. MTV 패턴이란 MVC 거의 같지만 View를 Template을 Controller를 View로 사용한다는점에서 약어만 다르고 거의 비슷하다. 


Business logic이랑 View를 따로 분리/설계 하여 개발하는 기법을 말하는것인데, 여기선 자세힌 다루진않을거고 그냥 내부 로직과 UI가 따로있어서 웹개발자와 디자이너는 서로엮이지않고 자기할것만 할수있는 방법이라고 보면되겠다. 



위와 같은 설문조사 사이트를 만들어볼건데.. 솔직히 모든 내용을 한꺼번에 이해하기엔 쉽지않을것이다. 


분명 url 처리 및 정규표현식도 알아야하고, html 및 python 문법 및 함수도 잘숙지해야한다.


그러나 따라하면서 만들어보고 잘작동하는 서버 소스코드를 분석하다보면 하나씩 이해해가며 접근하는 접근법보다 이해가 쉬울것이니, 잘따라해보길바람

(보다가 머리가 아프다면 복붙 추천!!)


1) 데이터베이스 지정 및 APP 등록


데이터베이스 설정은 settings.py 파일을 열어서 수정해주면된다.


여기서는 기본적으로 지정되어있는 SQLite3를 사용할것이므로 수정해주지않아도 된다.


cd mysite/mysite

vi settings.py 


그러나 위에서 polls 라는 어플리케이션을 추가해줬으므로, mysite/settings.py 파일에 polls 어플리케이션을 등록해줘야한다.


settings.py 파일을 열어서 polls 라는 앱을 등록해주도록하자.



2) 테이블 정의


설문조사를 하는 사이트라면 당연히 DB를 사용해야할것이다. polls/models.py 파일을 수정해주도록하자.


cd mysite/polls

vi models.py 


테이블 클래스는 django.db.models.Model 클래스를 상속받아 정의하며, 각 클래스 변수의 타입도 장고에서 미리 정의된 필드 클래스를 사용한다.


  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. class Question(models.Model):
  6.   question_text = models.CharField(max_length=200)
  7.   pub_date = models.DateTimeField('date published')
  8.  
  9.   def __unicode__(self):
  10.     return self.question_text
  11.  
  12. class Choice(models.Model):
  13.   question = models.ForeignKey(Question)
  14.   choice_text = models.CharField(max_length=200)
  15.   votes = models.IntegerField(default=0)
  16.  
  17.   def __unicode__(self):
  18.     return self.choice_text


3) Admin 사이트에 테이블 반영


추가된 DB 테이블을 아래와같이 반영해준다.


models.py 모듈에서 정의한 Question, Choice 클래스를 임포트하고 admin.site.register() 함수로 등록해주는 과정이다.


cd mysite/polls

vi admin.py


  1. from django.contrib import admin
  2.  
  3. # Register your models here.
  4.  
  5. from polls.models import Question, Choice
  6.  
  7. admin.site.register(Question)
  8. admin.site.register(Choice)


4) 데이터베이스 변경사항 반영


이제는 아래의 명령어로 생성한 데이터베이스를 반영하도록한다.


cd mysite

python manage.py makemigrations

python manage.py migrate 


makemigrations 명령어는 polls/migrations 디렉토리 하위에 마이그레이션 파일들이 생기고 이 마이그레이션 파일들을 이용하여 migrate 명령어 데이터에이스 테이블을 만들어준다.



변경사항이 잘 반영됬는지는 admin 사이트로 들어가서 관리자 아이디로 로그인하면 아래와 같이 확인할수있다.



5) 애플리케이션 개발하기 - View 및 Template 코딩해주기


앞서 polls 어플을 설계할때 3개의 페이지가 필요하였다. 물론 요청 흐름에대한 로직이 설계되어야하지만, 여기서는 4개의 URL과 뷰를 만들어서 어플을 설계해볼것이다.



① URL Conf 코딩해주기


url 경로는 app 경로에 나눠서 따로 해주는것이좋다


mysite 아래에 app 이 있으므로 우선 mysite url 부터 설정해준다.


cd mysite

vi urls.py


아래와 같이 코딩해주자.


  1. from django.conf.urls import include, include, url
  2. from django.contrib import admin
  3.  
  4. import polls
  5.  
  6. urlpatterns = [
  7.     url(r'^polls/', include('polls.urls',namespace = "polls")) ,
  8.     url(r'^admin/', include(admin.site.urls)),
  9. ]

cd mysite/polls/

vi urls.py



  1. from django.conf.urls import patterns, url
  2. from polls import views
  3.  
  4. urlpatterns = patterns('',
  5.         url(r'^$', views.index, name='index'),
  6.         url(r'^(?P<question_id>\d+)/$', views.detail, name='detail'),
  7.         url(r'^(?P<question_id>\d+)/results', views.results, name='results'),
  8.         url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
  9.     )

② 함수 index() 및 템플릿 작성

cd mysite/polls/

mkdir templates

mkdir templates/polls

cd templates/polls

vi index.html


  1. {if latest_question_list %}
  2.     <ul>
  3.     {for question in latest_question_list %}
  4.         <li><a href="/polls/{{question.id}}/">{{question.question_text}}</a></li>
  5.     {% endfor %}
  6.     </ul>
  7. {else %}
  8.     <p> No polls are available.</p>
  9. {% endif %}


③ polls 어플리케이션 view 함수 작성


cd mysite/polls/

vi views.py


  1. from django.shortcuts import render
  2. from django.shortcuts import get_object_or_404
  3. from django.http import HttpResponseRedirect, HttpResponse
  4. from django.core.urlresolvers import reverse
  5. from polls.models import Question
  6.  
  7. def index(request):
  8.     latest_question_list = Question.objects.all().order_by('-pub_date')[:5]
  9.     context = {'latest_question_list': latest_question_list}
  10.     return render(request, 'polls/index.html', context)
  11.  
  12. # Create your views here.
  13.  
  14. def detail(request, question_id):
  15.     question = get_object_or_404(Question, pk=question_id)
  16.     return render(request, 'polls/detail.html',{'question':question})
  17.  
  18. def vote(request, question_id):
  19.     p = get_object_or_404(Question, pk=question_id)
  20.     try:
  21.         selected_choice = p.choice_set.get(pk=request.POST['choice'])
  22.     except (KeyError, Choice.DoesNotExist):
  23.         return render(request, 'polls/detail.html', {
  24.                 'question':p,
  25.                 'error_message':"You didn't select a choice.",
  26.                 })
  27.     else:
  28.         selected_choice.votes += 1
  29.         selected_choice.save()
  30.         return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))
  31.  
  32. def results(request, question_id):
  33.     question = get_object_or_404(Question, pk=question_id)
  34.     return render(request, 'polls/results.html',{'question':question})


④ polls 어플리케이션 내에 detail.html 및 results.html 작성

cd mysite/polls/templates/polls

vi detail.html 


detail.html

  1. <h1> {{ question.question_text }}</h1>
  2.  
  3. {% if error_message %}<p><strong>{{ error_message }} </strong></p>{% endif %}
  4.  
  5. <form action="{% url 'polls:vote' question.id %}" method="post">
  6. {% csrf_token %}
  7. {% for choice in question.choice_set.all %}
  8.     <input type ="radio" name="choice" id="choice{{ forloop.counter }}" value="{{choice.id}}" />
  9.     <label for= "choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br/>
  10. {% endfor %}
  11. <input type = "submit" value="Vote" />
  12. </form>

results.html (위와 동일한 경로)

  1. <h1> {{ question.question_text }} </h1>
  2.  
  3. <ul>
  4. {% for choice in question.choice_set.all %}
  5.     <li> {{ choice.choice_text }} -- {{ choice.votes }} vote {{ choice.votes|pluralize }} </li>
  6. {% endfor %}
  7.  
  8. <a href= "{% url 'polls:detail' question.id %}"> Vote again?</a>



3. 최종 확인하기


위의 순서데로 잘따라해서 코딩해주었다면 polls로 접속시에 아래와 같은 메시지 화면을 볼수있을것이다.



이젠 admin 사이트로 들어가서 질문목록 Choices 와 Questions을 수정하여 설문항목을 추가해주도록하면된다.




* 참고 자료 


Django로 배우는 쉽고 빠른 파이썬 웹 프로그래밍