[코드잇] Django 감정 일기 #3

hyeo71·2023년 7월 4일
0

코드잇-감정일기

목록 보기
3/5

이전까지 CRUDRead를 작성하였고 남은 C, U, D를 작성한다.

1. 일기 작성(Create)

urls.py에서 create 부분을 주석 해제한다.
일기 작성은 Django Form을 사용하도록 한다.
앱 하위에 forms.py를 생성하고 Pageform class를 정의한다.
Form은 Form Field를 사용하는 방법과 Model Form을 사용하는 방법이 있는데 Form Field는 Model에 맞게 Field를 일일이 작성해야하기 때문에 Django가 Model에 맞게 Form을 도와주는 Model Form을 사용한다.

forms.py

from django import forms
from .models import Page


class PageForm(forms.ModelForm):
    class Meta:
        model = Page
        fields = "__all__"

views.pypage_create()를 정의한다.
일기 작성을 위해 페이지를 들어갈 경우 빈 form을 일기 작성 페이지(page-form)로 이동한다.
Form에 데이터를 입력하고 전송할 경우(POST) form 변수에 입력한 데이터 form를 저장하고 유효성 검사를 한 뒤 일기 상세 페이지(page-detail)로 이동한다.

views.py

def page_create(request):
    if request.method == "POST":
        form = PageForm(request.POST)
        if form.is_valid():
            new_page = form.save()
            return redirect("page-detail", page_id=new_page.id)
    else:
        form = PageForm()
    return render(request, "diarys/page_form.html", {"form": form})

추가하고 싶은 유효성 검사가 있다면 앱 하위에 validators.py를 생성하고 원하는 내용과 그 유효성 검사가 실패했을 경우 출력할 error를 작성한다.

validators.py

from django.core.exceptions import ValidationError


def validate_no_hash(value):
    if "#" in value:
        raise ValidationError("'#'은 포함될 수 없습니다.", code="hash-err")


def validate_no_numbers(value):
    for ch in value:
        if ch.isdigit():
            raise ValidationError("숫자는 들어갈 수 없습니다.", code="number-err")


def validate_score(value):
    if (value < 0) or (value > 10):
        raise ValidationError("0부터 10사이의 숫자만 입력 가능합니다.", code="score-err")

Model Form을 사용하기 때문에 models.py에 각 필드에 맞는 유효성을 추가한다.

models.py

from django.db import models
from .validators import validate_no_hash, validate_no_numbers, validate_score


class Page(models.Model):
    # 제목, 내용, 감정 상태, 감정 점수, 작성일
    title = models.CharField(max_length=100, validators=[validate_no_hash])
    content = models.TextField(validators=[validate_no_hash])
    feeling = models.CharField(
        max_length=50, validators=[validate_no_numbers, validate_no_hash]
    )
    score = models.IntegerField(validators=[validate_score])
    dt_created = models.DateField()

    def __str__(self):
        return self.title

마지막으로 page_form.html을 템플릿에 작성하면 Form을 사용한 일기 작성을 할 수 있다. page_form.html에서 이전과 같이 base.html를 extends하고 block에 원하는 모양에 맞춰 작성한다.
크로스 사이트 요청 위조(CSRF, Cross-Site Request Forgery)를 방지하기 위한 Django의 위조 방지 토큰을 form 태그에 적어준다.

page_form.html

{% extends './base.html' %}

{% block {comment} %}
  ...
    <form method="post">{% csrf_token %}
      ...
        <div class="input input-score">
          <p>감정 점수</p>
          {{form.score}}
          {% for error in form.score.errors %}
            <span>{{error}}</span>
          {% endfor %}
        </div>

        <!--제목, 상태 등 위와 동일-->
      ...
    </form>
  ...
{% endblock {comment} %}

2. 일기 수정(Update)

urls.py에서 update 부분을 주석 해제한다.
page_detail.html의 수정하기 링크 부분을 url 템플릿 태그를 사용하여 작성한다.
views.pypage_update()를 작성한다.
수정할 데이터는 데이터가 있으면 가져오고 없다면 404 에러를 출력하게 하는 get_object_or_404()를 사용하여 조회한다. (page_detail()에도 적용)
이후는 page_create와 동일하지만 PageForm()instance 파라미터가 들어간다. 이는 새로운 데이터를 만드는 것이 아닌 기존의 데이터를 수정하는 과정이기 때문에 수정하기 위해 조회한 데이터를 PageForm()에 넣어야 한다.

views.py

def page_update(request, page_id):
    object = get_object_or_404(Page, id=page_id)
    if request.method == "POST":
        form = PageForm(request.POST, instance=object)
        if form.is_valid():
            form.save()
            return redirect("page-detail", page_id=object.id)
    else:
        form = PageForm(instance=object)
    return render(request, "diarys/page_form.html", {"form": form})

3. 일기 삭제(Delete)

urls.py에서 delete 부분을 주석 해제한다.
page_detail.html의 삭제하기 링크 부분을 url 템플릿 태그를 사용하여 작성한다.
삭제할 데이터를 get_object_or_404()를 사용하여 조회한다.
데이터의 삭제를 재확인 할 page_confirm_delete.html을 템플릿에 작성하고 템플릿에서 form을 작성할 경우 데이터를 삭제하고 일기 목록 페이지(page-list)로 이동한다.

views.py

def page_delete(request, page_id):
    object = get_object_or_404(Page, id=page_id)
    if request.method == "POST":
        object.delete()
        return redirect("page-list")
    else:
        return render(request, "diarys/page_confirm_delete.html", {"object": object})

page_confirm_delete.html

...
    <form method='post'>{% csrf_token %}
      <ul>
        <li><input type="submit" value="지우기"></li>
        <li>
          <a href="{% url 'page-detail' object.id %}">남기기</a>
        </li>
      </ul>
    </form>
...

0개의 댓글