본문 바로가기

문돌이 존버/Django 스터디

장고(Django), CBV API Generic display views

반응형
본 글은 Holix의 "리액트와 함께 장고 시작하기 Complete" 강의를 듣고 작성한 일지입니다.

Detail View

Detail View는 1개 모델의 1개 Object에 대한 템플릿을 처리합니다. 모델명 소문자 이름의 Model Instance를 템플릿에 전달하는데, 이때 Model Instance는 지정 pk 혹은 slug에 대응하는 것입니다.

디폴트 값
slug_url_kwarg = 'slug'
pk_url_kwarg = 'pk'
=> 만약 다른 이름으로 설정한다면 해당 변수를 그 이름으로 선언하면 됩니다.

Detail View는 SingleObjectTemplateResponseMixin과 BaseDetailView를 상속받습니다.

post_detail = DetailView.as_view(model=Post) # template_name 지정 가능

위에서 template_name 을 지정할 수 있고 지정하지 않다 하더라도 장고 내에서 모델명으로 템플릿 경로를 유추합니다. 참고로 template_name 을 매번 지정하는 것보다 장고의 로직을 따르는 것이 좋다고 합니다.

아래처럼 queryset 이란 파라미터 역시 활용할 수 있습니다.

post_detail = DetailView.as_view(
    model=Post,
    queryset=Post.objects.filter(is_public=True)) # 공개된 게시물만 필터링

이때 로그인하지 않은 유저는 공개된 게시물만 보도록 하려면 아래처럼 self.request.user.is_authenticated 를 사용하여 로그인 정보를 확인할 수 있습니다.

class PostDetailView(DetailView):
    model = Post
    def get_queryset(self):
        qs = super().get_queryset()
        if not self.request.user.is_authenticated:
            qs = qs.filter(is_public=True)
        return qs

참고로 get_queryset(self) 함수 안에 있는 get_context_data(self, **kwargs) 함수를 보면 모델 객체를 'object' 키로 받게 되어 있습니다. 하지만 get_context_object_name(self, obj) 함수를 통해 저희가 따로 설정한 이름으로도 불러올 수 있습니다.

아래의 경우 'post'라는 키 값으로 모델 객체를 받아오는 예시입니다. 이때 'object'라고 해도 괜찮습니다.

def post_detail(request: HttpRequest, pk: int) -> HttpResponse:
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog1/post_detail.html', {
        'post': post, # or 'object': post도 가능
    })
참조
https://github.com/django/django/blob/main/django/views/generic/detail.py

ListView

ListView는 1개 모델에 대한 List 템플릿을 처리합니다. 모델명 소문자_list 이름의 QuerySet을 템플릿에 전달하게 되는데, 페이징 처리(paginate_by 사용) 역시 지원합니다.

ListView는 MultipleObjectTemplateResponseMixin과 BaseListView를 상속받습니다. Detail View와 마찬가지로 template_name 이 지정되지 않더라도 모델명으로 템플릿 경로를 유츄하게 됩니다.

post_list = ListView.as_view(model=Post, paginate_by=10)
참조
https://github.com/django/django/blob/main/django/views/generic/list.py

Bootstrap5

위에서 페이징한 것을 좀 더 이쁘게(?) 나타내는 방법 중 가장 쉬운 것은 이미 만들어진 템플릿을 활용하는 것인데요. django-bootstrap이 바로 템플릿을 이용할 수 있는 라이브러리입니다. 현재는 bootstrap5가 가장 최신 버전인 것으로 확인됩니다.

bootstrap5 공식문서
https://django-bootstrap5.readthedocs.io/en/latest/quickstart.html

먼저 라이브러리를 설치해줍니다.

pip install django-bootstrap5

# settings.py

INSTALLED_APPS = [
    # django apps
    ...,
    # third apps
    'django_extensions',
    'debug_toolbar',
    'django_bootstrap5',
    # local apps
    ...,
]
<!--post_list.html-->
{% load django_bootstrap5 %}
...
<body>
    {% if is_paginated %}
        {% bootstrap_pagination page_obj size="sm" justify_content="center" %} <!-- size 파라미터 value는 sm, md, lg 중 하나여야 함-->
    {% endif %}
</body>

참고
1. 페이지 숫자 크기는 size 파라미터로 조절하는데, 공식문서에 나온 small, large는 더 이상 유효한 값이 아닙니다. 에러 메시지를 보면 sm, md, lg 중 하나를 써야 한다고 하네요.
2. justify_content="center"는 bootstrap_pagination 함수가 리턴하는 함수 get_pagination_context 함수의 파라미터입니다. start, center, end 중 하나를 선택하면 그에 맞게 페이지 버튼 위치가 나타납니다.

 

728x90
반응형