제네릭 뷰 ListView

Ethan·2024년 1월 19일
0

Dear

목록 보기
9/13

이전 포스팅에서는 게시글 작성 페이지CreateView를 통해 구현하는 방법을 배웠다. 본 포스팅에서는 게시글 목록 페이지ListView를 통해 구현하는 방법을 알아본다.

1. ListView를 상속받은 클래스형 뷰 생성


1.1 기존 함수형 뷰 post_list

기존에 작성된 함수형 뷰는 아래와 같다. 주석처리 해준다.

#views.py

# def post_list(request):
#     posts = Post.objects.all().order_by("-dt_modified")  #생성일 기준 내림차순으로 변경
#     page = request.GET.get("page", 1)  #GET 요청 방식일 때 url에서 로컬 호스트/ 다음 page에 해당하는 값을 가져오고 값이 없다면 1을 기본값으로 함
#     paginator = Paginator(posts, 9)  #posts를 페이지 당 9개씩 호출
#     page_obj = paginator.get_page(page)  #가져온 page 값에 해당하는 페이지의 데이터를 불러온다
#     context = {"page_obj": page_obj}
#     return render(request, 'posts/post_list.html', context=context)

다시봐도 상당히 복잡하다.


1.2 변경된 클래스형 뷰 PostListView

ListView 제네릭 뷰를 상속받은 클래스를 생성한다.

#views.py

class PostListView(ListView):
    model = Post
    template_name = "posts/post_list.html"
    context_object_name = "posts"
    ordering = ["-dt_created"]
    paginate_by = 9
    page_kwarg = 'page'

접근할 모델을 정의하고, 렌더할 템플릿을 정의하고, context로 전달할 객체 이름을 정의하고, 정렬 기준을 오름차순으로 정의하고, 페이지 당 표기되는 게시글 수를 정의하고, 현재 페이지를 조회하기 위해 전달하는 이름을 정의한다.

기존처럼 복잡한 구조가 아닌, 변수에 대한 값만 정해주면 훨씬 간단하게 작성할 수 있다.


1.2.1 주의할 점

ListView를 상속받기 위해서는 import 해야한다.

ListViewcontext에 각 페이지에 해당하는 데이터를 전달할 때, 데이터의를 page_obj라는 으로 전달한다.

따라서 템플릿에서는 page_obj를 통해 각 페이지에 해당하는 데이터에 접근할 수 있다.

여기서 context_object_name 변수에 지정하는 값(여기서는 posts)을 통해서도 접근할 수 있다.

page_kwarg는 현재 페이지를 어떤 으로 조회하는지를 전달한다.

이해를 위해 템플릿처음으로 버튼을 살펴보면 <a class="able" href="?page=1">&lt&lt</a> 태그로 작성되어 있다.

여기서 url을 살펴보면 ?page=1로 작성된 것을 확인할 수 있는데 이는 1번 페이지로 이동하는 것을 말한다.

만약 템플릿에 작성된 page 이름이 pages로 변경되는 것과 같이 page_kwarg에 지정한 값과 다르다면, 원하는 페이지로 이동하지 못한다.


1.3 템플릿 수정

데이터에 접근하기 위한 템플릿 변수page_obj 또는 context_object_name에 지정한 값 posts 둘 중 하나를 사용해야 하는데, <dear> 프로젝트는 이미 page_obj로 사용하고 있기 때문에 변경하지 않아도 된다.

<!--post_list.html-->

{% block content %}
    <div class="btn_post">
        <a href={% url "post-create" %}>기록하기</a>
    </div>
    {% if page_obj %}
        <div class="post_container">
            {% for post in page_obj.object_list %}
                <div class="post"><a href="{% url "post-detail" post.id %}">
                    <h2 class="title">{{post.title}}</h2>
                    <p class="date">{{post.dt_created|date:"Y년 m월 d일 H시 i분"}}</p>
                    <p class="text">{{post.content}}</p>
                </a></div>
            {% endfor %}
        </div>

        <div class="pagination">
            {% if page_obj.has_previous %}
                <a class="able" href="?page=1">&lt&lt</a>
            {% else %}
                <a class="disable" onclick="return false;" href="#">&lt&lt</a>
            {% endif %}

            {% if page_obj.has_previous %}
                <a class="able" href="?page={{ page_obj.previous_page_number }}">&lt</a>
            {% else %}
                <a class="disable" onclick="return false;" href="#">&lt</a>
            {% endif %}


            {% for page_number in page_obj.paginator.page_range %}
                {% if page_number == page_obj.number %}
                    <a class="disable" id="current" onclick="return false;" href="#">{{ page_number }}</a>
                {% elif page_obj.number <= 3 and page_number <= 5 %}
                    <a class="able" href="?page={{ page_number }}">{{ page_number }}</a>
                {% elif page_obj.number > page_obj.paginator.num_pages|add:-3 and page_number >= page_obj.paginator.num_pages|add:-4 %}
                    <a class="able" href="?page={{ page_number }}">{{ page_number }}</a>
                {% elif page_number >= page_obj.number|add:-2 and page_number <= page_obj.number|add:2 %}
                    <a class="able" href="?page={{ page_number }}">{{ page_number }}</a>
                {% endif %}
            {% endfor %}
        
            
            {% if page_obj.has_next %}
            <a class="able" href="?page={{ page_obj.next_page_number }}">&gt</a>
            {% else %}
            <a class="disable" onclick="return false;" href="#">&gt</a>
            {% endif %}
            
            {% if page_obj.has_next %}
            <a class="able" href="?page={{ page_obj.paginator.num_pages }}">&gt&gt</a>
            {% else %}
            <a class="disable" onclick="return false;" href="#">&gt&gt</a>
            {% endif %}
        </div>

        {% else %}
        <div class="blank">
            <p>
                등록된 게시글이 없습니다.<br>
                게시글을 등록해보세요.
            </p>
        </div>
    {% endif %}

{% endblock content %}

1.4 url 패턴 변경

url 패턴에서 post_listPostListView로 변경해야 한다.

urls.py

urlpatterns = [
    # path('', views.index),
    path('', views.PostListView.as_view(), name="post-list"),
    path('posts/new/', views.PostCreateView.as_view(), name="post-create"),
    path('posts/<int:post_id>/', views.PostDetailView.as_view(), name="post-detail"),
    path('posts/<int:post_id>/edit/', views.post_update, name="post-update"),
    path('posts/<int:post_id>/delete/', views.post_delete, name="post-delete"),
]
profile
글로 쓰면 머리 속에 정리가 되...나?

0개의 댓글

관련 채용 정보