🎮

005. 페이지 작성하기

1. 메인 페이지

1.1. URL 설정

URL 라우팅

URL 라우팅이란 사용자의 요청 주소, 즉 URL에 따라 어떤 앱의 어떤 페이지를 보여줄지를 설정하는 것을 말합니다. 예를 들어 [프로젝트 URL]/admin/ 주소로 요청이 오면 admin앱의 페이지를 보여주는 식입니다.
이러한 설정이 MBIT/urls.py에 정의되어 있습니다.
from django.contrib import admin from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), ]
MBIT/urls.py
 
[프로젝트 URL]/로 요청이 오면 우리가 만들 메인 페이지가 보이도록 해봅시다.
urls.py 를 다음과 같이 수정합니다.
from django.contrib import admin from django.urls import path from main import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index) ]
여기서 views.indexmain/views.py에서 작성할 함수입니다. 이 설정은 [프로젝트 경로]로 요청이 오면 main/views.py에 있는 index라는 함수를 실행하겠다는 의미입니다.
 

1.2. 뷰 함수 정의

main/views.pyindex 함수를 다음과 같이 정의합니다.
from .models import Question, Developer, Choice def index(request): developers = Developer.objects.all() context = { 'developers': developers, } return render(request, 'index.html', context=context)
  • index 함수는 return 값으로 'index.html'을 render 해주며 이 코드는 index.html을 페이지로 보여주겠다는 뜻입니다.
  • Developer.objects.all() 은 모든 Developer의 요소들을 리스트같은 형태로 반환합니다.
    • 💡
      정확히는 QuerySet이라는 자료구조지만 List 처럼 활용이 가능합니다.
  • context 딕셔너리에 담은 요소들은 index.html에서 변수처럼 사용할 수 있습니다. 자세한 것은 다음 3) 템플릿 정의에서 설명합니다.
 

1.3. 템플릿 정의

장고에서 html 파일들을 별개로 장고 템플릿이라고 부릅니다. 장고는 기본적으로 템플릿 파일들을 각 앱 폴더 안의 templates라는 폴더 안에서 찾습니다. 하지만 기본적으로 생성되어 있지는 않으므로 직접 templates 폴더를 생성해야합니다. 우리의 main 앱 폴더 안에 templates 폴더를 생성하고 그 안에 index.html 템플릿 파일을 만듭니다.
notion imagenotion image
 

1.3.1 장고 템플릿 언어

장고 템플릿에서는 장고만의 문법인 장고 템플릿 언어(django template language)를 사용할 수 있습니다. html 파일 안에서 원래 쓸 수 없었던 변수, 반복문, 제어문 등을 사용할 수 있습니다. 대체로 파이썬 문법과 비슷하므로 쉽게 익힐 수 있습니다.
  • 변수 - 장고문서
    • 출력하고자 하는 변수를 {{ variable }} 형식으로 출력할 수 있습니다.
      {{ question }}
 
  • for - 장고문서
    • 반복문으로 {% for [변수] in [반복가능한 개체] %} 형식으로 사용합니다. 끝날 때 반드시 {% endfor %}가 필요합니다.
      {% for question in questions %} ... {% endfor %}
 
  • if - 장고문서
    • 제어문으로 {% if [조건] %} 형식으로 사용합니다. {% elif [조건] %} 또는 {% else %}으로 elif, else 문도 사용이 가능합니다. 끝날 때 반드시 {% endif %} 가 필요합니다.
      {% if 조건1 %} ... {% elif 조건2 %} ... {% else %} ... {% endif %}
 
index.html 파일을 다음과 같이 작성합니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>index</title> </head> <body> <h1>index 페이지입니다</h1> <a href="form/">설문 하기</a> {% for developer in developers %} <p>{{ developer.name }} : {{ developer.count }}명</p> {% endfor %} </body> </html>
 
이제 [프로젝트 URL]로 접속하면 해당 페이지가 보여지게 됩니다.
notion imagenotion image

2. 설문 페이지

2.1 URL 설정

[프로젝트 URL]/form/으로 요청이 오면 우리가 만들 설문 페이지가 보이도록 해봅시다.
urls.py 를 다음과 같이 수정합니다.
from django.contrib import admin from django.urls import path from main import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index), path('form/', views.form), ]
여기서 views.formmain/views.py에 작성할 함수입니다. 이 설정은 [프로젝트 URL]/form/로 요청이 오면 main/views.py에 있는 form이라는 함수를 실행하겠다는 의미입니다.
 

2.2 뷰 함수 정의

main/views.pyform 함수를 다음과 같이 정의합니다.
def form(request): questions = Question.objects.all() context = { 'questions': questions, } return render(request, 'form.html', context)
  • form 함수의 역할은 form.html 을 페이지로 보여주는 역할입니다.
  • Questions.objects.all() : 모든 Question 요소를 불러옵니다.
 

2.3 템플릿 정의

templates 폴더를 생성하고 그 안에 form.html 템플릿 파일을 만들고 다음과 같이 작성합니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>form</title> </head> <body> <form action="/result/" method="post"> {% csrf_token %} {% for question in questions %} <h3>{{ question.number }}번 {{ question.content }}</h3> {% for choice in question.choice_set.all %} <div> <input type="radio" name="question-{{ question.number }}" id="choice-{{ choice.pk }}" value="{{ choice.developer.pk }}"> <label for="choice-{{ choice.pk }}">{{ forloop.counter }}. {{ choice.content }}</label> </div> {% endfor %} <hr> {% endfor %} <input type="submit" value="제출하기"> </form> </body> </html>
 
이제 [프로젝트 URL]/form/로 접속하면 해당 페이지가 보여지게 됩니다.
notion imagenotion image

3. 결과 페이지

3.1. URL 설정

[프로젝트 URL]/result/로 요청하면 우리가 만들 결과 페이지가 보이도록 해봅시다.
urls.py 를 다음과 같이 수정합니다.
from django.contrib import admin from django.urls import path from main import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index), path('form/', views.form), path('result/', views.result), ]
여기서 views.formmain/views.py에 작성할 함수 입니다. 이 설정은 [프로젝트 URL]/result/로 요청이 오면 main/views.py에 있는 result 라는 함수를 실행하겠다는 의미입니다.
 

3.2. 뷰 함수 정의

main/views.pyresult 함수를 다음과 같이 정의합니다.
def result(request): # 문항 수 N = Question.objects.count() # 개발자 유형 수 K = Developer.objects.count() # 개발유형마다 몇 개인지 저장할 리스트 counter[1] = (1번 유형 점수(개수)) counter = [0] * (K + 1) for n in range(1, N+1): developer_id = int(request.POST[f'question-{n}'][0]) counter[developer_id] += 1 # 최고점 개발 유형 best_developer_id = max(range(1, K + 1), key=lambda id: counter[id]) best_developer = Developer.objects.get(pk=best_developer_id) best_developer.count += 1 best_developer.save() context = { 'developer': best_developer, 'counter': counter } return render(request, 'result.html', context)
  • form 함수의 역할은 form.html 을 페이지로 보여주는 역할입니다.
  • Developer.objects.get(pk=best_developer_id)
    • id값이 best_developer_id인 요소를 찾습니다.
 

3.3. 템플릿 정의

templates 폴더를 안에 form.html 템플릿 파일을 만들고 다음과 같이 작성합니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>result</title> </head> <body> <h1>결과 페이지</h1> <p>{{ developer.name }}</p> <a href='/'>메인화면</a> <a href="/form">다시하기</a> </body> </html>
 
이제 [프로젝트 URL]/result/로 접속하면 해당 페이지가 보여지게 됩니다.
notion imagenotion image
 

4. Django 개발 루틴

이제 Django를 어떻게 개발해야 하는지 순서가 감이 오시나요?
다시 한번 정리해보자면,
💡
urls.py에서 url을 설정해준다 👉 views.py에서 url에 접속 했을 때 실행해 줄 함수를 작성한다 👉 templates 안에 템플릿 파일을 만들고 사용자가 접근할 수 있도록 코드를 작성한다.