[Django] Chapter 2. 장고의 기본 요소 익히기(2-06~2-10)

최하린·2023년 2월 9일
0

Django

목록 보기
3/4

점프 투 장고 필사 https://wikidocs.net/73236
해당 게시물은 점프 투 장고를 참고하여 작성하였습니다.

2-06 데이터 저장

01. 답변등록 폼

질문 상세 템플릿(question_detail.html)에 다음처럼 답변을 저장할 수 있는 폼(form)을 추가한다.

<form action="{% url 'pybo:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea> # 답변의 내용을 입력할 수 있는 텍스트 창
<input type="submit" value="답변등록"> # 답변 등록 버튼

form 태그 바로 밑에 보이는 {% csrf_token %}은 보안에 관련된 항목으로 form으로 전송한 데이터가 실제 웹 페이지에서 작성한 데이터인지를 판단하는 가늠자 역할을 한다. 그러므로 항상 form 태그 밑에 위치시켜야 한다.

02. URL 매핑

질문 상세 템플릿에 {% url 'pybo:answer_create' question.id %}처럼 pybo:answer_create 별칭을 사용했는데, answer_create 별칭을 지정해주지 않았기 때문에 오류가 발생할 것이다.

pybo/urls.py에 다음과 같은 URL 매핑을 등록해야 한다.

from django.urls import path
from . import views

app_name = 'pybo'

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('answer/create/<int:question_id>/', views.answer_create, name='answer_create'),
]

views.answer_create 함수가 호출될 것이다.

03. 뷰 함수

위에서 정의한 views.answer_create 함수를 pybo/views.py 파일에 다음처럼 추가한다.

from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from .models import Question

(... 생략 ...)

def answer_create(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())
    return redirect('pybo:detail', question_id=question.id)

답변 등록시 텍스트창에 입력한 내용은 answer_create 함수의 첫번째 매개변수인 request 객체를 통해 읽는다. 즉, request.POST.get('content')로 텍스트창에 입력한 내용을 읽을 수 있다. request.POST.get('content')는 POST로 전송된 폼(form) 데이터 항목 중 content 값을 의미한다. 그리고 답변을 생성하기 위해 question.asnswer_set.create 를 사용하였다.

답변을 생성한 후 질문 상세 화면을 다시 보여주기 위해 redirect 함수를 사용했다. redirect 함수는 페이지 이동을 위한 함수이다. 여기에서는 pybo:detail 별칭에 해당하는 페이지로 이동하기 위해 redirect 함수를 사용했다. 그리고 pybo:detail별칭에 해당하는 URL은 question_id가 필요하므로 question.id를 인수로 전달했다.

04. 답변 저장 및 조회

다음과 같이 수정하고 url을 호출하면 답변이 잘 저장된 것을 볼 수 있다.

<h1>{{ question.subject }}</h1>
<div>
    {{ question.content }}
</div>
<h5>{{ question.answer_set.count }}개의 답변이 있습니다.</h5> # 답변의 총 개수를 의미
<div>
    <ul>
    {% for answer in question.answer_set.all %}
        <li>{{ answer.content }}</li>
    {% endfor %}
    </ul>
</div>
<form action="{% url 'pybo:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변등록">
</form>

2-07 스태틱

파이보에 스타일시트를 적용하여 화면을 꾸며볼 것이다.

01. 스태틱(static) 디렉터리

스타일시트의 파일은 장고의 스태틱 디렉터리에 저장해야 하므로 config/settings.py 파일에 다음과 같이 추가한다.

(... 생략 ...)

STATIC_URL = 'static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

(... 생략 ...)

STATICFILES_DIRS라는 리스트 변수를 추가하고 BASE_DIR/'static'은 C:\projects\mysite\static 디렉터리를 의미하므로 다음처럼 static 디렉터리를 생성한다.

(mysite) c:\projects\mysite> mkdir static

02. 스타일시트

꾸며주기 위해 style.css 파일을 만들어 다음과 같이 작성한다.

textarea{
    width:100%; /*답변 등록시 사용하는 텍스트 창의 넓이를 100%로 함 */
}
input[type=submit] {
    margin-top:10px; /* 답변등록 버튼 상단에 10 픽셀의 마진을 설정 */
}

03. 템플릿에 스타일 적용

위에서 작성한 스타일시트 파일을 질문 상세 템플릿에 적용한다. question_detail.html 파일에 다음과 같이 코드를 추가해주면 된다.

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
<h1>{{ question.subject }}</h1>
(... 생략 ...)

템플릿에 스타일시트와 같은 스태틱 파일을 사용하기 위해서는 템플릿 최상단에 {% load static %} 태그를 삽입해야지 {% static ... %}와 같은 템플릿 태그를 사용할 수 있다.

2-08 부트스트랩

부트스트랩에 관한 내용은 점프 투 장고를 보면서 해도 이해가 잘 안 가서 따로 공부해야 할 것 같다...
일단 책을 보고 따라하니 이렇게 깔끔한 화면으로 바꼈다.

2-09 템플릿 상속

지금까지 만든 페이지는 표준 HTML 구조가 아니므로 웹 표준을 지키는 HTML 문서를 작성해야 한다.

01. 표준 HTML 구조

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" type="text/css" href="/static/bootstrap.min.css">
    <title>Hello, pybo!</title>
</head>
<body>
(... 생략 ...)
</body>
</html>

표준 HTML 문서의 구조는 위의 예처럼 html, head, body 엘리먼트가 있어야 하며, CSS 파일 링크는 head 엘리먼트 안에 있어야 한다. 또한 head 엘리먼트 안에는 meta, title 엘리먼트 등이 포함되어야 한다.

점프 투 장고 내용에 따르면 태그와 엘리먼트 정의는 다음과 같다.

02. 템플릿 상속

앞에서 작성한 질문 목록, 질문 상세 템플릿을 표준 HTML 구조가 되도록 수정해야 한다. 그런데 템플릿 파일들을 모두 표준 HTML 구조로 변경하면 body 엘리먼트 바깥 부분(head 엘리먼트 등)은 모두 같은 내용으로 중복될 것이다. 그러면 CSS 파일 이름이 변경되거나 새로운 CSS 파일이 추가될 때마다 모든 템플릿 파일을 일일이 수정해야 한다.

상속(extend)

장고는 이런 중복과 불편함을 해소하기 위해 템플릿 상속(extend) 기능을 제공한다. 템플릿 상속은 기본 틀이 되는 템플릿을 먼저 작성하고 다른 템플릿에서 그 템플릿을 상속해 사용하는 방법이다.

base.html

base.html은 기본 틀이 되는 템플릿이다.
projects/mysite/templates 경로에 base.html 파일을 만들어 다음과 같이 작성해준다.

{% load static %}
<!doctype html>
<html lang="ko">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" type="text/css" href="{% static 'bootstrap.min.css' %}">
    <!-- pybo CSS -->
    <link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
    <title>Hello, pybo!</title>
</head>
<body>
<!-- 기본 템플릿 안에 삽입될 내용 Start -->
{% block content %}
{% endblock %}
<!-- 기본 템플릿 안에 삽입될 내용 End -->
</body>
</html>

위와 같이 코드를 작성하면 !doctype html 부분에 오류가 발생하는데 기능상에는 문제가 없으므로 무시하면 된다고 한다.

bast.html 템플릿은 모든 템플릿이 상속해야 하는 템플릿으로 표준 HTML 문서의 기본 틀이 된다. body 엘리먼트 안의 {% block content %} 와 {% endblock %} 템플릿 태그는 base.html을 상속한 템플릿에서 개별적으로 구현해야 하는 영역을 의미한다.

question_list.html

question_list.html의 {% load static %}

부분을 다음과 같이 수정해준다. ```python {% extends 'base.html' %} {% block content %}
    (... 생략 ...)

</table>
{% endblock %} ``` 템플릿 상속을 적용한 후 질문 목록, 질문 상세를 조회해보면, 화면에 보여지는 것은 동일하지만 표준 HTML 구조로 변경된 것을 확인할 수 있다.

style.css

그리고 부트스트랩 적용으로 인해 style.css의 내용은 필요가 없어졌으므로 내용을 지워도 된다. 이 파일은 이후 부트스트랩으로 표현할 수 없는 스타일을 위해 사용할 것이므로 파일 자체를 삭제하지는 말고 내용만 삭제한다.

2-10 폼

질문 등록

질문 등록하기 버튼을 생성한다.

0개의 댓글

관련 채용 정보