---
description: >-
  이전에 만들었던 블로그에 CRUD 중 create와 read에 해당하는 `새 글 작성` 기능을 추가해보자. admin 계정을 이용하지 않고,
  사용자가 직접 포스트를 작성할 수 있도록 만들어볼 것이다.
---

# \[Django 7] '새 글 작성' 기능 만들기

> [블로그 model 만들기](https://velog.io/@hidaehyunlee/Django-%EB%B8%94%EB%A1%9C%EA%B7%B8-model-%EB%A7%8C%EB%93%A4%EA%B8%B0) 와 이어지는 실습입니다. 이전 소스코드는 [이 곳](https://github.com/hidaehyunlee/fitstsite_project/tree/57a15377acc0f1d89b7b6020ebf5e76948ef31d0) 을 참고하세요.

## 1. CRUD란?

> create, read, update, delete

사용자 인터페이스가 갖추어야 할 기능(정보의 참조/갱신/검색)을 가르키는 용어이다. 우리가 웹이든 앱이든 어떤 소프트웨어를 사용한다면 반드시 일어나는 행위일 것이다.

이전에 만들었던 블로그에 CRUD 중 create와 read에 해당하는 `새 글 작성` 기능을 추가해보자. admin 계정을 이용하지 않고, 사용자가 직접 포스트를 작성할 수 있도록 만들어볼 것이다.

조금 더 구체적으로 고민해보자면, 아래 기능이 필요할 것 같다.

* 글을 작성할 수 있는 form을 가진 새 글 작성 페이지
* 새 글을 작성하면 데이터를 저장하는 함수

## 2. '새 글 작성' 기능 만들기

### 1) view 만들기

hello 앱의 views에 `home`, `new`, `create` 라는 3개의 함수를 생성한다.

```python
# hello/views.py

from django.shortcuts import render, redirect
from .models import Blog

def home(request):
    blogs = Blog.objects
    return render(request, 'home.html', {'blogs' : blogs})

def new(request):
    return render(request, 'new.html')

def create(request):
```

* `home`, `new` 함수는 각각 홈화면과 새 글 작성하는 화면 html을 렌더링한다.
*   `create`는 글 작성 요청(POST)이 들어오면 객체 생성해서 데이터에 값을 넣어준다.

    코드가 조금 복잡하니 일단 나중에 작성해보자.

### 2) new, create url 추가하기

프로젝트 폴더의 urls.py에 `new`, `create` url을 추가한다.

```python
# firstsite/urls.py

from django.contrib import admin
from django.urls import path
import hello.views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', hello.views.home, name='home'),
    path('new/', hello.views.new, name='new'),
    path('create/', hello.views.create, name='create'),
]
```

### 3) home.html에 '새 글쓰기' 링크 추가하기

```python
# hello/templates/home.html 


<h1>블로그 글 목록입니다.</h1>
<br>
<a href="{% url 'new' %}">새 글쓰기</a>

{% for blog in blogs.all%}
<div>
    <h1> {{blog.title}}</h1>
    <p> {{blog.created_at}}</p>
    <p> {{blog.updated_at}}</p>
    <p>{{blog.body}}</p>
</div>
{%endfor%}
```

일반적인 html에서 링크는 아래 코드처럼 작성한다.

```markup
<a href="/new">새 글쓰기</a>
```

하지만 django에서는 코드의 유지보수를 용이하게 하기 위해 urls.py에서 정의했던 **url 이름을 템플릿태그**를 사용해 넣어준다.

### 4) new.html 에 form 추가하기

![image](https://user-images.githubusercontent.com/37580034/87180936-6c32f180-c31c-11ea-8a13-b3deb7aee797.png)

* 새 글을 입력받기 위해 `form` 을 추가한다.&#x20;
* `post` 방식으로 입력받은 데이터를 `create` 뷰로 보낸다.

```python
# hello/templates/new.html

<form action="{% url 'create' %}" method="post">
    {% csrf_token %}
    <div>
      <label for="title">제목</label><br>
      <input type="text" name="title" id="title">
    </div>
    <div>
        <label for="content">내용</label><br>
      <textarea name="body" id="body" cols="30" rows="10"></textarea>
    </div>
    <input type="submit" value="글쓰기">
  </form>
```

* **\{% csrf\_token % }** : 장고에서는 기본적으로 CSRF 토큰을 이용해 CSRF공격을 방지한다.&#x20;

> **CSRF 공격이란?** CSRF 공격(Cross Site Request Forgery)은 웹 어플리케이션 취약점 중 하나로, 인터넷 사용자(희생자)가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격

### 5) view의 create 함수 작성하기

* form action을 통해 받은 데이터를 `post` 객체에 넣어준다.
* `post` 객체에 저장한 데이터를 `save()` 메서드로 데이터베이스에 저장한다.
* 다시 `'home'` 으로 리다이렉트한다.

```python
# hello/views.py

def create(request):
    if(request.method == 'POST'):
        post = Blog()
        post.title = request.POST['title']
        post.body = request.POST['body']
        post.save()
    return redirect('home')
```

* `redirect`는 render와 다르게 인자 전달 불가능(어디로 이동할 건지만 명시).
