작정하고 장고 36강 - Articleapp 구현

IkSun·2023년 5월 24일

작정하고 장고

목록 보기
36/46

지금까지 CRUD 에 해당하는 view 를 작성하였다

계정을 만들떄에는 단일 객체(single object)만 해당되었다

  • ex) detailView 에서는 특정 계정의 정보

최종적으로 게시판 같은 형태의 Article 을 만드는 것이 목표이기 떄문에 여러 객체(multiple object)를 다룰 수 있는 view 가 필요

여기서 나오는게 List view 이다. -> 장고에서 제공
추가적으로 pagination (페이지화 시킨다 -> 한페이지에 몇개의 게시글을 보여줄 것인지)

pagination

  • 페이지에 객체를 생성한다는 의미
  • 구글에서 여러 검색 페이지 1 2 3 .. 이 pagination 을 의미한다.
  • Infinite Scroll : 무한 스크롤 형식도 존재한다
    • ex) 페이스북, 인스타그램, 핀터레스트 등
    • 구현하기 위해서 추가적인 JavaScript 필요

ListView 의 형태

  • ListView 코드 위해 주요하게 사용할 템플릿의 두가지 html

    • article_List
    • page_obj
  • article_List

    • 게시글의 리스트를 의미 (아이템 꾸러미 역할)
    • 이 안에 객체들의 각각의 장보를 다 담고 있어서
    • html 에다가 카드형 레이아웃을 가져온다면
    • 각각 article_list 를 다 뿌려주는 역할
  • page_obj

    • 페이지를 만들어줄떄 생성하는 번호들을 만들어 그 페이지로 갈 수 있도록 링크를 만들어주는 역할

코딩 시작

views.py 에 ArticleListView 작성

# articleapp/views.py
from msilib.schema import ListView

...
# 추가
class ArticleListView(ListView):
    model = Article
    context_object_name = 'article_List'
    template_name = 'articleapp/list.html'
    paginate_by = 5

urls.py 에서 List 로 향하는 라우팅 수정

  • 기존에는 list 에 대해서 임시로 TemplateView 라는 것을 사용하였다.
  • 이를 우리가 만든 ArticleListView 로 연결하여 수정한다.
from django.urls import path
from django.views.generic import TemplateView

from articleapp.views import ArticleCreateView, ArticleDetailView, ArticleUpdateView, ArticleDeleteView, ArticleListView

app_name = 'articleapp'

urlpatterns = [
    path('list/', ArticleListView.as_view(), name='list'), # 수정

    path('create/', ArticleCreateView.as_view(), name='create'),
    path('detail/<int:pk>', ArticleDetailView.as_view(), name='detail'),
    path('update/<int:pk>', ArticleUpdateView.as_view(), name='update'),
    path('delete/<int:pk>', ArticleDeleteView.as_view(), name='delete'),
]

픽섬에서 가져온 이미지들 전부 제거

  • articleapp/templates/articleapp/list.html 수정
<!--articleapp/templates/articleapp/list.html-->
...
<!--html 부분 수정-->
<div class="container">
    {% for article in article_list %}
    <a href=" {% url 'articleapp:detail pk=article.pk %}">
        <div>
            <img src="{{ article.image.url }}" alt="">
        </div>
    </a>
</div>
...

템플릿 내부에 snippets 디렉토리 생성

  • snippets는 코드 조각이라는 의미로 다음 코드를 따로 빼서 card.html 파일로 보관해줄 것
  • 전체 카드의 레이아웃, 내용을 바꾸고 싶다면 이 card.html 만 수정하면 전체 반영
<!--templates/snippets/card.html-->
<div>
   <img src="{{ article.image.url }}" alt="">
</div>

list.html 수정

  • snippets 에 있는 card.html 을 가져온다
  • card.html 내부의 article 이라는 것을 with 구문을 사용하여서 밖에 있는 article 과 연결
  • 즉, article_list 로 부터 하나씩 뽑아올 article 이
  • sinppets 내부 card.html 의 article 과 같다는 것을 명시해주는 것
<!--articleapp/templates/articleapp/list.html-->
...
<div class="container">
    {% for article in article_list %}
    <a href=" {% url 'articleapp:detail pk=article.pk %}">
        {% include 'snippets/card.html' with article=article %}
    </a>
</div>
...

게시글이 없을 경우

  • article_list 는 게시글이 아예 없다면 존재하지 않기 떄문에, article_list 가 없을 경우 게시글이 없다는 것을 화면에 출력
...

    {% if article_list %}
    <div class="container">
        {% for article in article_list %}
        <a href=" {% url 'articleapp:detail' pk=article.pk %}">
            {% include 'snippets/card.html' with article=article %}
        </a>
        {% endfor %}
    </div>
    <script src="{% static 'js/magicgrid.js' %}"></script> <!--js 를 컨테이너 내부로 이동시키기--> 
    {% else %}
    <div class="text-center">
        <h1>No Articles YET! </h1>
    </div>
    {% endif %}

...

게시글 만들어보기

http://127.0.0.1:8000/articles/list/page=2

  • get 방식으로 page 값에 2 를 넣어주면 다음 페이지로 이동함.

pagination 버튼 만들기

    {% if article_list %}
    <div class="container">
        {% for article in article_list %}
        <a href=" {% url 'articleapp:detail' pk=article.pk %}">
            {% include 'snippets/card.html' with article=article %}
        </a>
        {% endfor %}
    </div>
    <script src="{% static 'js/magicgrid.js' %}"></script> <!--js 를 컨테이너 내부로 이동시키기-->
    {% else %}
    <div class="text-center">
        <h1>No Articles YET! </h1>
    </div>
    {% endif %}

	<!-- 추가 -->
    {% include 'snippets/pagination.html' with page_obj=page_obj %}
  • snippets 안에다가 pagination.html 만들기
<!--templates/snippets/pagination.html-->
<div style="text-align: center; margin:1rem 0;">
  {% if page_obj.has_previous %} <!--현재 페이지 page_obj 객체가 이전 페이지를 가지고 있다면-->
  <!--get 방식으로 이전 페이지의 번호를 넘겨주면서 이전 페이지로 넘어가는 링크를 만들어줌-->
  <a href="{% url 'articleapp:list' %}?page={{ page_obj.previous_page_number }}"
    class="btn btn-secondary rounded-pill">
      {{ page_obj.previous_page_number }}
  </a>
  {% endif %}
  <!-- 현재 있는 페이지 -->
  <a href="{% url 'articleapp:list' %}?page={{ page_obj.number }}"
    class="btn btn-secondary rounded-pill active">
      {{ page_obj.number }}
  </a>
  {% if page_obj.has_next %} <!-- 다음 페이지가 있다면 -->
  <!-- 다음페이지로 향하는 링크 만들어주기-->
  <a href="{% url 'articleapp:list' %}?page={{ page_obj.next_page_number }}"
    class="btn btn-secondary rounded-pill active">
      {{ page_obj.next_page_number }}
  </a>
  {% endif %}
</div>

articleapp -> detail.html 수정

{% extends 'base.html'%}

{% block content %}

  <div>
    <div style="text-align: center; max-width: 700px; margin: 4rem auto;">

      <!--게시글의 제목-->
      <h1>
        {{ target_article.title }}
      </h1>
      <!-- 닉네임 표시 -->
      <h5>
        {{ target_article.writer.profile.nickname }}
      </h5>
      <hr>

      <!--게시글의 이미지-->
      <img style="width: 100%; border-radius: 1rem; margin: 2rem 0;"
              src=" {{ target_article.image.url }}" alt="">

      <!-- 게시글의 내용 -->
      <p>
        {{ target_article.content }}
      </p>

      <!-- 인증 과정 포함-->
      {% if target_article.writer == user %}
      <!-- 게시글 업데이트-->
      <a href="{% url 'articleapp:update' pk=target_article.pk %}"
      class="btn btn-primary rounded-pii col-3">
        Update
      </a>

      <!-- 게시글 삭제 -->
      <a href="{% url 'articleapp:delete' pk=target_article.pk %}"
      class="btn btn-danger rounded-pii col-3">
        Delete
      </a>
      {% endif %}
      <hr> <!-- 밑에 코멘트가 들어갈 공간 분리-->

    </div>
  </div>

{% endblock %}

업로드중..

commit

profile
공부한 것 기록용

0개의 댓글