ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django] CURD 로 블로그 구현하기(READ)
    Python & Django 2021. 6. 1. 20:33

    이번 포스팅에는 MTV 패턴을 활용해 CRUD (쓰기, 읽기, 수정하기, 삭제하기)가 가능한 블로그를 구현해보겠습니다. 우선 읽기 기능부터 시작합니다.

     

    지난 포스팅인 Model 생성하기에서 이어서 하겠습니다.


    1. Read 설계

    CRUD 중 Read의 기능을 생각해보면 우선, 전체 게시글 목록을 보여주는 페이지와 각각의 게시글을 보여주는 상세 페이지로 나눠볼 수 있습니다.

     

    여기서 목록 페이지는 home 으로, 상세 페이지는 detail 로 만들어보겠습니다.

     

    앞에서 MTV 패턴에서 공부했듯이, 목록 페이지를 만드는 것은 MTV 패턴을 따릅니다.

     

    1. 목록 페이지를 열었을 때,

    해당요청 처리하는 view(모델을 통해 blog 데이터를 불러옴) - url - template(목록 페이지 - home.html)

     

    2. 디테일 버튼을 눌렀을 때,

    해당 요청을 처리하는 view(모델을 통해 blog 데이터를 불러옴) - url - template(상세 페이지 - detail.html)

     

    홈페이지를 열어서 요청을 보내면 모델에서 게시글 목록 데이터를 가져오는 view 와 이를 다시 보여주는 템플릿이 필요합니다. 그리고, 각 게시글마다 상세페이지 버튼을 눌렀을 때 이를 받아 각 게시글을 보여주는 view 와 상세 페이지를 보여줄 템플릿(detail 페이지)가 필요합니다.


    2. 목록 페이지 (템플릿, 뷰, url )

    템플릿 생성

    일단 템플릿부터 만들겠습니다. blog 폴더에 templates 폴더를 만들고, home.html 파일을 생성합니다. 그리고 안에 html 의 기본적인 코드를 작성합니다.

     

     

    뷰 만들기

    다음은 home.html 에 접속했을 때 요청을 받아 처리를 해줄 view 를 만들어야 합니다. views.py 에 아래 코드를 작성합니다.

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

    이 코드를 살펴보면, 우선 models 에서 Blog 를 불러옵니다. 그리고 매개변수 request 를 받아서 home 함수를 정의합니다. 이때, blogs 변수에 Blog 모델의 객체들을 모두 담아줍니다.

     

    그리고 home.html 을 불러오는데(render) 매개변수인 request 와 딕셔너리 자료형으로 'blog': blogs 라고 키와 밸류를 전달합니다. 

    이렇게 보내주면 home.html 에서 blogs 를 이용해 그 안에 담은 Blog 모델의 객체들을 모두 불러올 수 있을 것입니다.

     

    url 만들기

    이제 views.py 에서 home 액션과 home.html 을 연결해주는 url 을 작성할 차례입니다.

    from django.contrib import admin
    from django.urls import path
    from blog.views import *
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', home, name="home"),
    ]

    우선 from blog.views import * 로 views의 블로그로부터 함수들을 불러옵니다. 여기서 * 로 불러오게 되면 blog.views 안의 모든 함수들을 사용할 수 있습니다.

     

    그리고 path 에 ''(첫페이지), home( * 로 불러온 views 의 액션), name="home" (name 을 지정하면 연결된 html 에서 해당 이름값으로만 사용할 수 있음) 을 넣어줍니다.

     

    템플릿 완성하기

    이제 url 로 연결한 home.html 에 코드를 추가해 게시글 목록을 보여줘야 합니다.

     

    그 전에, home.html 로 어떤 데이터가 넘어오는지 확인해보겠습니다. html 파일에서 views 에서 넘겨준 데이터를 사용하려면 {} 로 묶어서 작성하면 됩니다. 

     

    <body>
        <h1>이구의 블로그</h1>
    
        {{blogs}}
    </body>

    home.html 에 위와 같이 코드를 작성하고 서버를 열어보면 위 이미지와 같이 쿼리셋이 전달된 것을 볼 수 있습니다. 즉, views.py 의 home 에서 처리한 blogs 들이 잘 전달되는 것을 확인할 수 있습니다.

     

    그리고 게시글 목록을 보여주려면, 반복문을 사용해 이 쿼리셋에 담긴 blogs 의 컬럼 데이터들을 하나씩 꺼내오면 됩니다.

     

    <h1>이구의 블로그</h1>
    
        {% for blog in blogs %}
            <h2>{{ blog.title }}</h2>
            <p>{{ blog.writer }}</p>
            <p>{{ blog.body }}</p>
        {% endfor %}

    반복문 안에 blog.title 로 부르면 blogs 안의 blog의 title 컬럼의 데이터를 불러올 수 있습니다. 마찬가지로 writer, body 도 불러옵니다.

     

    서버를 열어보면 위와 같이 이전에 어드민에서 작성한 데이터들이 제대로 불러와졌습니다. 그런데 라일락 게시물의 body 가 너무 길어서 이를 줄여주도록 하겠습니다.

     

    models.py 에서 Blog 클래스 안에 summary 함수를 정의줍니다. 이는 파이썬의 슬래싱 개념을 활용한 것으로 30번째 인덱스까지 보여주는 것입니다.

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

    그리고 home.html 에 가서 새로 정의한 함수를 적용합니다.

    <h1>이구의 블로그</h1>
    
        {% for blog in blogs %}
            <h2>{{ blog.title }}</h2>
            <p>{{ blog.writer }}</p>
            <p>{{ blog.summary }}</p>
        {% endfor %}

    홈페이지를 새로고침하면 위와 같이 슬래싱이 잘 적용되어 body 부분이 짧게 나옵니다.


    3. 디테일 페이지 (템플릿, 뷰, url )

    이번에는 각 게시물의 상세 페이지를 만들 단계입니다.

     

    과정은 위와 유사합니다.

     

    템플릿 만들기

    마찬가지로 템플릿부터 시작합니다. templates 폴더에 detail.html 파일을 만들어줍니다.

     

    뷰 만들기

    이제 뷰에서 detail 을 만들어줍니다.

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

    여기는 home 과 비교했을 때 매개변수로 request 와 함께 id 도 전달해야 합니다.

     

    home 은 목록을 보여주기 때문에 각각의 id 가 필요 없었지만, detail 페이지는 url 을 통해 각 게시물(Blog의 객체)에 접근해야 하기 때문에 id 를 전달해야 합니다.

     

    그리고 blogs 가 아닌 게시물 하나를 열어보기 때문에 blog 변수에 Blog.objects.get(id = id)으로 해당 객체의 id 에 맞는 객체를 하나 담아줍니다.

     

    그리고 딕셔너리로 blog 를 전달하면서 detail.html 을 불러옵니다.

     

    url 만들기(path-converter)

    urls.py 에서 detail url 을 작성할 때 주의해야 하는데요, 아래 코드를 보면 path 에 <str:id> 를 넣어줍니다. 이러한 방식을 path-converter 라고 하는데 이를 사용하면 url 주소에 id 를 각각 넣어줄 수 있습니다.

     

    예를 들어, 게시글이 100개가 있다고하면 100개의 path를 작성해야 하는데, path-converter 를 사용해 객체의 id 값을 넣어주면 해당 id 에 맞는 url 을 불러올 수 있습니다.

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

     

    상세 페이지 버튼 만들기(home.html 수정)

    이제 home.html 에서 각 게시물의 상세 페이지(detail)로 들어가는 버튼을 만들어줍니다.

    <h1>이구의 블로그</h1>
    
        {% for blog in blogs %}
            <h2>{{ blog.title }}</h2>
            <p>{{ blog.writer }}</p>
            <p>{{ blog.summary }}</p>
            <a href="{% url 'detail' blog.id %}">게시글 보기</a>
        {% endfor %}

    버튼은 a 태그로 만들어주며 url 은 {% url 'detail' blog.id %} 로 작성하는데, detail 은 urls.py 에서 입력해준 name="detail" 이고, blog.id 를 넣어준 이유는 해당 url 이 해당 객체의 id 값을 가지고 views.py 의 details 에 요청을 보내야 하기 때문입니다. 이때, request 와 id 가 매개변수로 detail 에 전달됩니다.

     

    detail.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>Detail</title>
    </head>
    <body>
        <h1>제목: {{ blog.title }}</h1>
        <p>작성자: {{ blog.writer }}</p>
        <p>작성일자: {{ blog.pub_date }}</p>
        <hr>
        <p>{{ blog.body }}</p>
    </body>
    </html>

    저는 위와 같이 detail.html 을 완성하였습니다. 이제 서버를 열어보겠습니다.

    위 이미지는 각각 home.html, detail.html 인데요, 각 게시글마다 상세 페이지로 넘어가는 '게시글 보기' 버튼을 만들었고, 상세 페이지로 이동하면 불러온 데이터들이 잘 나오는 것을 확인할 수 있습니다.


    Read 에 대해 다시한번 정리해보면, 

    Read 에는 두 가지 기능이 있다. '객체의 목록 보여주기', '각 객체의 상세 페이지 보여주기' 기능인데, 둘의 가장 큰 차이점은 상세 페이지의 경우 매개변수에 id 를 넣어주고 그 id 에 맞는 객체의 컬럼에 있는 데이터들을 불러와 보여준다는 것입니다.

     

    그리고, urls.py 에서 path 작성 시 path-converter 를 이용해 url 에 요청에 맞는 각 객체의 id를 넣어준다는 것입니다.

     

Designed by Tistory.