포스트 작성 페이지 만들기

Posted on 2021-08-25 by GKSRUDTN99
Django로 웹사이트 만들기 장고

테스트 코드 작성하기

1. /blog/create_post/라는 URL로 방문자가 접근하면 포스트 작성 페이지가 정상적으로 열려야 함.

2. 타이틀은 Create Post - Blog로 되어 있어야 함.

3. 메인 영역에는 Create New Post라는 문구가 있어야 함.

# blog/tests.py

    def test_create_post(self):
        response = self.client.get('/blog/create_post/')
        self.assertEqual(response.status_code, 200)
        soup = BeautifulSoup(response.content, 'html.parser')

        self.assertEqual('Create Post - Blog', soup.title.text)
        main_area = soup.find('div', id='main-area')
        self.assertIn('Create New Post', main_area.text)

views.py에 CreateView 추가하기

1. CreateView를 상속받는 PostCreate 클래스를 새로 정의한다.

2. 어떤 모델을 사용할 것인지 명시하고, 모델에서 사용할 필드명을 리스트로 작성한다.

# blog/views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView, CreateView
from .models import Post, Category, Tag

(... 생략...)


class PostCreate(CreateView):
    model = Post
    fields = ['title', 'hook_text', 'content', 'head_image', 'file_upload', 'category']

urls.py 작성

/blog/create_post/를 처리하는 코드를 작성한다.

# blog/urls.py
from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('create_post/', views.PostCreate.as_view()),
    path('tag/<str:slug>/', views.tag_page),
    path('category/<str:slug>/', views.category_page),
    path('<int:pk>/', views.PostDetail.as_view()),
    path('', views.PostList.as_view()),
]

템플릿 파일 작성

base.html을 확장하여 post_form.html을 작성한다.

타이틀을 작성하고, {{ form }}<table> 태그로 감싼다.

views.py에서 CreateView를 상속받아 만든 클래스는 테이블 형태로 폼을 구성하기 때문에, <table> 태그가 필요하다.

<!--blog/templates/blog/post_form.html-->
{% extends 'blog/base.html' %}

{% block head_title %}Create Post - Blog{% endblock %}


{% block main_area %}
    <h1>Create New Post</h1>
    <hr/>
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <table>
            {{ form }}
        </table>
        <button type="submit" class="btn btn-primary float-end">Submit</button>
    </form>
{% endblock %}

enctype="multipart/form-data는 파일도 같이 전송하겠다는 의미이다.

CreateView로 작성된 form은 action="/blog/create_post/"와 같이 적어줄 필요가 없다.

장고에서 알아서 처리하므로, 특별한 목적이 있지 않는 한 사용하지 않는다.

{% csrf_token %}을 통해 csrf 토큰을 발급한다.

템플릿 모양 개선

현재 post_form.html페이지는 우측에 카테고리와 검색 창이 위치하지만, 카테고리를 불러오는 쿼리셋을 작성하지 않아 이상하게 보인다.

post_form.html은 우측 위젯 없이 넓은 공간을 제공하는 base_full_width.html을 새로 작성하여 이 파일을 확장하도록 한다.

<!--blog/template/blog/base_full_width.html-->
<!DOCTYPE html>
{% load static %}
<html>
<head>
    <meta charset="UTF-8">
    <title>{% block head_title %}Blog{% endblock %}</title>
    <link href="{% static 'blog/bootstrap/bootstrap.min.css' %}" rel="stylesheet" media="screen">
    <script src="https://kit.fontawesome.com/1205323533.js" crossorigin="anonymous"></script>

</head>
<body>
{% include 'blog/navbar.html' %}

<div class="container my-3">
    <div class="row">
        <div class="col-12" id="main-area">
            {% block main_area %}
            {% endblock %}
        </div>
    </div>
</div>
{% include 'blog/footer.html' %}

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>
</body>
</html>
<!--blog/templates/blog/post_form.html-->
{% extends 'blog/base_full_width.html' %}

{% block head_title %}Create Post - Blog{% endblock %}


{% block main_area %}
    <h1>Create New Post</h1>
    <hr/>
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <table>
            {{ form }}
        </table>
        <button type="submit" class="btn btn-primary float-end">Submit</button>
    </form>
{% endblock %}