샘플 Feedback App

샘플 - Feedback 예제

간단한 샘플 App으로서 지금까지 설명한 Feedback App에 대해 보다 자세히 알아보자. Feedback App은 간단한 코멘트를 입력받고, 편집하고, 전체 리스트를 보여주는 간단한 App이다. 아래 그림은 전체 리스트 (/feedback/list) 보기과 편집 (/feedback/edit/2) 폼에 대한 샘플 화면이다.


1. 뷰 (View)

View (feedback/views.py) 파일에 리스트(list), 피드백 추가(create), 피드백 편집(edit) 등 3개의 함수 를 작성하였다.


create 함수는 이전 아티클에서 이미 설명하였으므로 list와 edit을 간단히 설명하면, list 는 모든 Feedback 데이타를 가져와 feedbacklist.html 템플릿에 전달하여 전체 피드백 리스트를 작성한다. edit 는 id 를 URL에서 전달받아 (/feedback/edit/2 와 같이) 해당 id를 갖는 Feedback 데이타 하나를 feedback.html 템플릿에서 수정하게 한다.

from django.shortcuts import render, redirect
from .models import *
from .forms import FeedbackForm

def list(request):
    feedbacks = Feedback.objects.all()
    return render(request, 'feedbacklist.html', {'feedbacks': feedbacks})

def create(request):
    if request.method=='POST':
        form = FeedbackForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect('/feedback/list')
    else:
        form = FeedbackForm()

    return render(request, 'feedback.html', {'form': form})

def edit(request, id):
    fb = Feedback.objects.get(pk=id)
    if request.method=='POST':
        form = FeedbackForm(request.POST, instance=fb)
        if form.is_valid():
            form.save()
        return redirect('/feedback/list')
    else:
        form = FeedbackForm(instance=fb)

    return render(request, 'feedback.html', {'form': form})

특히 edit() 함수에서 하나의 Feedback 객체를 Feedback.objects.get() 을 통해 가져온 후, 이를 FeedbackForm(instance=fb) 폼 생성자에 "instance=" 을 써서 전달하고 있음에 유의하자 (주: edit() 함수의 else 부분). 이렇게 하면 해당 Feedback 객체의 필드값들이 채워진 FeedbackForm 객체가 생성된다.

또한, 편집 내용이 저장되어 POST로 전달될 때, FeedbackForm(request.POST, instance=fb) 와 같이 표현되고 있는데, 이는 save()시 해당 Feedback객체(fb)가 request.POST 데이타로 갱신되게 한다 (주: edit() 함수의 if 블럭).

2. 템플릿

Feedback 템플릿들은 ./feedback/templates 폴더에 있으며, 기본 템플릿 (./templates/base.html) 을 확장한 템플릿들이다.

우선 기본 템플릿인 base.html의 내용은 다음과 같다. 이 기본 템플릿에는 2개의 block (title과 content block)을 사용하였다.

{% load staticfiles %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Web</title>

    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
    <div class="container">
        <h2>
            My Web
        </h2>
    </div>

    <div class="container">
        {% block title %}
        {% endblock title %}
    </div>

    <div class="container">
        {% block content %}
        {% endblock content %}
    </div>
</body>
</html>

다음은 feedback.html의 내용으로 create와 edit 함수에 의해 사용되는 템플릿이다.

{% extends "base.html" %}

{% block title %}
    <h3>
        Your Feedback
    </h3>
{% endblock title %}

{% block content %}
    <p>
        <a href="{% url 'list' %}">Goto List</a>
    </p>

    <div>
        <form method="POST">
            {% csrf_token %}
            <table class="table">
                {{ form.as_table }}
            </table>
            <button type="submit">저장</button>
        </form>
   </div>

{% endblock content %}

다음은 feedbacklist.html의 내용으로 list 함수에 의해 사용되는 템플릿이다.

{% extends "base.html" %}
{% load staticfiles %}

{% block title %}
    <h3>
        <img src="{% static 'images/note.jpg' %}" style="width:50px" />
        Feedback List
    </h3>
{% endblock title %}

{% block content %}
    <p>
        <a href="{% url 'create' %}">+ Create New</a>
    </p>

    <table class="table">
        <tr><th>Id</th><th>Name</th><th>Email</th><th>Comment</th></tr>
        {% for item in feedbacks %}
            <tr>
                <td>
                    <a href="{% url 'edit' id=item.id %}">{{ item.id }}</a>
                </td>
                <td>{{ item.name }}</td>
                <td>{{ item.email }}</td>
                <td>{{ item.comment }}</td>
            </tr>
        {% endfor %}
    </table>
{% endblock content %}

특히 위 템플릿에서 ID 컬럼을 보면, HTML a 태그를 사용하여 ID를 누르면 편집(edit) 기능을 호출하게 하였다. a 태그의 href 값을 보면, url 이름이 edit 으로 되어 있으며, 여기에 해당 ROW의 id 값을 추가로 설정하고 있다. 이 태그 표현식은 템플릿 엔진에 의해 예를 들어 "/feedback/edit/2" 과 같이 해석된다.

3. App URL 매핑

뷰(View)의 각 함수들에 상응하는 URL 매핑은 ./feedback/urls.py 에 아래와 같이 정의하였다. 여기서 각 url 마다 name을 정의하였는데, 이 name은 위 템플릿의 {% url %} 태그에서 사용되고 있다.

from django.conf.urls import url
from feedback import views

urlpatterns = [
    url(r'^list', views.list, name='list'),
    url(r'^create', views.create, name='create'),
    url(r'^edit/(?P\d+)/$', views.edit, name='edit'),
]

그리고 이미 설명되었지만, Django 프로젝트의 urls.py 파일 안에는 feedback App에 대한 URL 매핑이 다음과 같이 설정되어 있다.

urlpatterns = [
    #... 다른 매핑 생략...
    url(r'^feedback/', include('feedback.urls')),
]
Python 프로그래밍 실습

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.