Today Sangmin Learned
article thumbnail
Published 2021. 7. 21. 14:42
[Django] CRUD - R, C Django
728x90

1. Read

1. blog 폴더에 templates 폴더 생성하고 home.html 만들기

 

2. 이 새로 만든 home.html을 각각 crud2/blog/views.py와 crud2/crud2/urls.py에 연결해주기

from django.shortcuts import render
from .models import Blog

# Create your views here.
def home(request):
    blog = Blog.objects.all()
    return render(request, 'home.html', {'blogs': blogs})

Blog 내부에 있는 모든 객체들을 blogs라는 변수에 담고, 그 blogs를 이 view에서 blogs라는 이름으로 사용한다는 뜻이다.

from django.contrib import admin
from django.urls import path
from blog.views import *

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home, name='home')
]

blog 내부의 views.py 전체를 가져온 뒤(3행), home의 URL은 127.0.0.1:8000 그 자체이므로 path 내부에 아무 값도 설정하지 않는다.

 

3. home.html 작성하기

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BLOG</title>
  </head>
  <body>
    <h1>Blog Project</h1>
    {{ blogs }}
  </body>
</html>

그대로 서버를 켜서 보면 쿼리셋 형태로 출력이 됨. 이는 전달받은 모델의 객체 목록이다. 그래서 이를 하나하나 쪼개서 보기 위해서는 home.html에 아래와 같은 처리를 해줘야 한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BLOG</title>
  </head>
  <body>
    <h1>Blog Project</h1>
    {% for blog in blogs%}
        {{ blog }}
    {% endfor %}
  </body>
</html>

blogs 내부에 있는 각 값들을 blog라 칭하고, 그 블로그들을 for문을 돌면서 하나씩 출력한다는 뜻. 이렇게 되면 이제 제목이 뜬다. 우리는 근데 제목이 필요하지 않다. 객체 내부의 값들(writer, title, pub_date, body)이 필요하다. 이를 위해 models.py에서 __str__(self)를 지워줘서 객체 형태로 바꿔주고 HTML을 아래와 같이 수정해준다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BLOG</title>
    <style>
      body {
        text-align: center;
      }
    </style>
  </head>
  <body>
    <h1>Blog Project</h1>
    <div class="container">
      {% for blog in blogs%}
      <div>
        <h3>{{ blog.title }}</h3>
        <p>{{ blog.writer}}</p>
		    {{ blog.body }}
      </div>
      {%endfor %}
    </div>
  </body>
</html>

마찬가지로 blogs 내부에 있는 blog에 대해 title, writer, body 순으로 출력하게끔 하는 명령어이다. 하는 김에 살짝 가독성이 떨어진다고 판단되어 스타일링까지 넣어줬다.

이제 잘 뜨는 것을 볼 수 있다.

 

4. 127.0.0.1:8000/admin에 들어가서, Blogs 내부에

title: lorem ipsum
writer: admin
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

으로 글을 하나 작성해준다. 그 후 다시 메인으로 가보면

이렇게 되어있다. 우리는 이렇게 모든 글을 다 보여줄 게 아니라, 최대 100자 이내로 축약을 해주려고 한다.

5. models.py에 가서 Blog 클래스 맨 마지막에

    def summary(self):
        return self.body[:100]

를 추가해주고 home.html에서 {{ blog.body }} 대신에 {{ blog.summary }}를 넣어준다.

다시 확인해보니 100자까지만 나오게 변경되었다.

그 다음으로는, detail 페이지를 만들것이다.

 

6. templates 폴더 내부에 detail.html 폴더를 만들어준 뒤 views.py에 아래와 같이 만들어준다.

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

# Create your views here.
def home(request):
    blogs = Blog.objects.all()
    return render(request, 'home.html', {'blogs': blogs})

def detail(request, id):
    blog = get_object_or_404(Blog, pk = id)
    return render(request, 'detail.html', {'blog': blog})

get_obect_or_404는, 존재하지 않는 페이지에 대한 요청이 있을 경우 404 처리를 해줄 수 있게 하는 명령어이다. 두가지를 매개변수로 받는데, 하나는 Blog(models.py에서 가져온 것)이고, 하나는 pk이다. 여기서 pk란 기본키를 의미하는데, 쉽게 말하면 그 페이지임을 식별해줄 수 있는 기본값 이라고 생각하면 된다. 그러니까, id를 기본키로 설정함으로써 detail 페이지 내부의 여러 글들을 구분짓겠다는 것이다.

이 id는 urls.py에서 설정함으로써 가져올 수 있다.

from django.contrib import admin
from django.urls import path
from blog.views import *

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home, name='home'),
    path('<int:id>', detail, name='detail'),
]

여기서 id는 앞서 정한 매개변수의 이름(pk = id)이다. int는 정수형을 의미하고, 이에 따르면 이제 127.0.0.1:8000/1 의 경우 id가 1인 값의 detail.html을 보여주게 되는 것이다.

 

7. 이 detail로 이동하기 위해 home.html에 링크를 넣어준다.

<a href="{% url 'detail' blog.id %}">...more</a>

 

8. 마지막으로 detail.html 템플릿을 아래와 같이 넣어준다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Detail</title>
    <style>
      body {
        text-align: center;
      }
    </style>
  </head>
  <body>
    <h1>{{blog.title}}</h1>
    <div>
      작성자: {{blog.writer}}
      <br />
      날짜: {{blog.pub_date}}
    </div>
    <hr />
    <p>{{blog.body}}</p>
  </body>
</html>

이제 서버를 켜보면.. 아래와 같이 디테일 페이지로 이동하는 링크가 생성되었고

누를 경우 아래와 같이 id값을 가진 detail 페이지가 나타난다.

 

2. Create

이제 새로운 글 작성을 해볼 것이다.

1. crud2/blog/templates에 new.html을 만들고 views.py와 urls.py에 연결해준다. 위에서 했으므로 다시 쓰지 않고 넘어간다.

2. home.html에서 new.html로 가는 링크를 만들어준다.

<h4><a href="{% url 'new' %}">New Post</a></h4>

3. new.html을 완성해준다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>New Post</title>
  </head>
  <body>
    <h1>New Blog Entry</h1>
    <form action="" method="post">
      {%csrf_token%}
      <p>제목: <input type="text" name="title" /></p>
      <p>작성자: <input type="text" name="writer" /></p>
      본문: <br /><textarea name="body" id="" cols="30" rows="10"></textarea
      ><br />
      <button type="submit">작성하기</button>
    </form>
  </body>
</html>

여기서 method="POST"란, 쉽게 얘기해서 데이터를 만들기 위한 요청이라고 생각하면 된다. POST의 경우 CSRF 공격을 방지할 수 있다. 이 CSRF 공격은 여기를 보면 되고, 이 공격을 막아주기 위해 POST 사용시 {% csrf_token %}을 꼭 넣어줘야한다.

 

4. 이제 views.py에서 현재 껍데기뿐인 new가 기능을 할 수 있게끔 create 함수를 넣어준다.

def create(request):
    new_blog = Blog()
    new_blog.title = request.POST['title']
    new_blog.writer = request.POST['writer']
    new_blog.body = request.POST['body']
    new_blog.pub_date = timezone.now()
    new_blog.save()
    return redirect('detail', new_blog.id)

각 명령어는 Blog 모델을 가져온 뒤 title, writer, body를 각각 데이터 생성하게끔 하고 마지막에 저장해주는 방식이다. 그리고 여기까지 다 잘 됐을 경우 마지막에 detail 페이지로 이동하게끔 redirect 설정을 해줬다.

이렇게 하고, urls.py에 아래 명령어를 넣어주는 것을 잊지 말아야 한다.

    path('create/, create, name='create')

 

5. 그 다음 우리가 위에서 만들어줬던 new.html의 form action에서 비어있는 부분을 채워준다.

 <form action="{%url 'create'%}" method="post">

이는, 버튼을 눌렀을 때 create로 이동하게끔 하는 명렁어이다.

 

6. 이제 home을 보면

이렇게 New Post가 생성되었다. 눌러보면

이러한 form을 가진 페이지로 이동하고, 작성을 하고 작성하기를 누르면 아래 사진처럼 detail 페이지로 이동한다.

 

'Django' 카테고리의 다른 글

[Django] Template 상속, 앱 분리, Static  (0) 2021.07.22
[Django] CRUD - U, D  (0) 2021.07.22
[Django] Model & Admin  (2) 2021.07.21
profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!