9 Sat

TIL

[배프의 오지랖 파이썬 웹프로그래밍]

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

3. 1 프로젝트 만들기

프로젝트 명 : polls

장고 설치

  • pip install django

프로젝트 생성

  • django-admin startproject config .

3. 2 웹서버

웹 서버 시작하기

  • python manage.py runserver

포트 변경

  • python manage.py 8080

  • python manage.py 0.0.0.0:8080

  • python manage.py 0:8000

  • (근데 나는 잘 안된다)

3.3 설문조사 앱 만들기

앱 생성

  • python manage.py startapp polls

3.4 첫번째 뷰 만들기

polls/views.py

from django.shortcuts import render
from django.http import HttpResponse
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
# Create your views here.

뷰를 만들면 이 뷰를 호출하기 위한 URL이 있어야 한다. URL 연결을 위해 polls 폴더에 urls.py 생성

polls/urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index')
]

path 함수는 path(route, view, kwargs, name) 형태로 호출한다.

  • route : 주소를 의미

  • view : 1의 주소로 접근했을 때 호츌할 뷰

  • 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 파일을 참조할 수 있도록 해준다.

3.5 데이터베이스 만들기

config/settings.py 의 76번째 줄에는 데이터 베이스 설정이 있다.

  • ENGINE : 어떤 종류의 데이터베이스를 사용할지 설정

    • 기본적으로 다음과 같은 4가지를 사용할 수 있다

      • django.db.backends.sqlite3

      • django.db.backends.postgresql

      • django.db.backends.mysql

      • django.db.backends.oracle

데이터베이스 초기화

  • python manage.py migrate

3.6 모델 만들기

모델은 데이터베이스의 구조도이다. 데이터베이스에 어떤 테이블을 만들고 어떤 컬럼을 갖게 할 지 결정하며 컬럼의 제약 조건까지도 모델에서 결정한다.

polls/models.py

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=20)
    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을 이용해 동작하는 기능들을 가지고 있다.

  • 각 클래스 변수들은 필드 값을 가지며 이 필드는 자료형과 같다.

  • ForeignKey는 다른 모델과의 관계를 만들기 위해서 사용한다. Choice 모델이 ForeignKey로 Question 모델을 갖는다는 것은 Choice 모델이 Question에 소속된다는 것을 의미한다.

  • 모델을 완성하면 데이터베이스에 적용해야 한다. 이 때 사용하는 명령어는 migrate 이다. 또한, 이 명령을 사용하려면 polls 앱이 현재 프로젝트에 설치되어 있다고 config/settings.py 에 명시해줘야 한다.

config/settings.py

INSTALLED_APPS = [
    'polls.apps.PollsConfig'
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.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을 실행하거나 문제가 있는 쿼리를 판단할 수 있다.

  • 그러나 장고를 사용하면 쿼리문을 몰라도 ORM을 통해 데이터베이스에 접근할 수 있다.

데이터베이스 반영

  • python manage.py migrate polls 0001

  • 이 명령을 통해 데이터베이스에 변경사항을 반영하여 테이블을 생성하고 초기화 할 수 있다.

3.7 모델에 함수 추가하기

Question 모델과 Choice 모델에 __str__ 메서드를 추가한다.

polls/models.py

from django.db import models
from django.utils import timezone
import datetime

class Question(models.Model):
    question_text = models.CharField(max_length=20)
    pub_date = models.DateTimeField('date published')
    def __str(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str(self):
        return self.choice_text

모델을 작성한 후에 단순 메서드 변경은 migrate를 할 필요가 없다.

3.8 관리자 페이지 확인

관리자 페이지에 접근하기 위해서는 관리자 계정이 필요하다.

  • python manage.py createsuperuser

관리자 페이지에서 Question 모델을 관리하려면 이 모델을 등록해야 한다. admin.py 파일에서 다음 코드를 입력한다.

from django.contrib import admin
from .models import Question
admin.site.register(Question)

3.9 여러 가지 뷰 추가

튜표 앱의 메인 페이지 이후 여러 가지 뷰를 추가한다

  • 투표 목록

  • 투표 상세

  • 투표 기능

  • 투표 결과

views.py

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

polls/urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

3개의 뷰를 만들고 URL을 연결했다. index뷰와 다른 점은 각 URL에 있는 화살괄호는 변수를 의미하며 이 부분에 해당하는 값을 뷰에 인자로 전달한다.

polls/views.py

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

기능이 있는 뷰를 만들었지만 MTV 패턴에 따르지 않은 형태이다. 템플릿을 만들어 파이썬 코드와 HTML 코드를 분리한다.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if latest_question_list %}
    <ul>
        {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
        {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

</body>
</html>

polls/views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

loader를 이용해 index.html을 불러오고 미리 만들어 놓은 context 변수를 이용해 전달한다. 하지만 이런 절차가 약간 불편하기 때문에 장고에서는 render라는 단축함수를 제공한다.

polls/views.py

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {
        'latest_question_list': latest_question_list,
    }
    return render(request, 'polls/index.html', context)

render 메서드는 request와 템플릿 이름, 사전형 객체를 인자로 받는다. 사전형 객체는 템플릿에서 사용할 변수를 의미.

템플릿이 반영된 메인 화면

3장 이어서...

Last updated

Was this helpful?