def get_board_set_from_board_group(request, board_group_id):
...완료!!!
def home(request):
...완료!!!
def board(request, board_url):
...이번장!!!
def post_detail(request, board_url, pk):
...
def reply_write(request, board_url, pk):
...
def rereply_write(request, board_url, pk):
...
def reply_delete(request, board_url, pk):
...
def rereply_delete(request, board_url, pk):
...
def like(request, board_url, pk):
...
[ get_board_set_from_board_group 함수 리팩토링 ]
get_board_set_from_board_group 리팩토링 정보 보기
[ home 함수 리팩토링 ]
home 페이지 성능 개선 Board View 코드 리팩토링
home 페이지 좋아요, 댓글 수 Board View 코드 리팩토링
Board 앱의 View 함수들을 살펴보니 총 9개의 코드가 존재합니다.
하나하나씩 불필요한 코드를 제거하거나 리팩토링해 보겠습니다
엔드포인트를 재구성하기 위해 일반 게시판, 검색 게시판, 태그 게시판에서 공용으로 사용되는 함수를 Service Layer로 분리하여 각각의 새로운 View에서 해당 로직을 사용할 수 있도록 코드 작업을 했습니다..
이제 전체 검색 게시판을 위한 endpoint 분리를 해보겠습니다.
from django.urls import path
from .views import *
app_name = 'board'
urlpatterns = [
path('board', get_all_boards, name='all_board_posts'),
path('board/tag/<str:tag_name>', get_tagged_posts, name='get_tagged_posts'),
path('board/<str:board_url>', get_board_posts, name='get_board_posts'),
...
]
위의 path('board', get_all_board_posts, name='all_board_posts')
와 같이 하나의 새로운 endpoint 를 만드려고 합니다.
get_board_posts
View 안에 있는 코드를 리펙토링해서, 작업하려고 합니다.
지금 get_board_posts
의 문제점은 View Layer라는 점입니다.
즉, path('board', get_all_board_posts, name='all_board_posts')
에서 get_all_board_posts
를 사용하려면 공통적인 부분을 Service Layer로 이용해야 한다는 점입니다.
def get_board_posts(request, board_url):
board_detail = get_object_or_404(Board, url=board_url)
board_posts_request = BoardPostsRequest.of(request)
paging_data = web_paging(
get_active_filtered_posts(
search=board_posts_request.search,
board_urls=[board_url],
).select_related(
'author'
).order_by(
'-id'
),
int(request.GET.get('page', 1)),
10,
5,
)
page_posts = paging_data['page_posts']
has_previous = page_posts.has_previous()
has_next = page_posts.has_next()
return render(
request,
'board/board_detail.html',
BoardPostsResponse(
board_detail_info=BoardDetailInfo(
name=board_detail.name,
info=board_detail.info,
url=board_detail.url,
board_img_url=board_detail.board_img.url if board_detail.board_img else None,
name_background_color=board_detail.name_background_color,
name_text_color=board_detail.name_text_color,
info_background_color=board_detail.info_background_color,
info_text_color=board_detail.info_text_color,
),
posts=[
BoardPost(
id=post.id,
title=post.title,
short_body=post.short_body(),
board_url=post.board.url,
author_nickname=post.author.nickname,
created_at=post.created_at.strftime('%Y-%m-%d'),
like_count=post.like_count,
reply_count=post.reply_count,
image_url=post.post_img.url if post.post_img else static('logo.ico'),
) for post in page_posts
],
has_previous=has_previous,
has_next=has_next,
previous_page_number=page_posts.previous_page_number() if has_previous else None,
current_page_number=page_posts.number,
next_page_number=page_posts.next_page_number() if has_next else None,
last_page_number=page_posts.paginator.num_pages,
page_range=paging_data['page_range'],
).model_dump()
)
리펙토링을 해봅시다.
Service Layer 에 함수를 새로 생성합니다.
def get_board_paged_posts(search: str = None, page: Union[int, str] = 1, board_urls: List[str] = None, tag_names: List[str] = None):
paging_data = web_paging(
get_active_filtered_posts(
search=search,
board_urls=board_urls,
tag_names=tag_names,
).select_related(
'author'
).order_by(
'-id'
),
int(page),
10,
5,
)
return paging_data
그리고 이 함수로 기존의 코드들을 리펙토링합니다.
def get_board_posts(request, board_url):
board_detail = get_object_or_404(Board, url=board_url)
board_posts_request = BoardPostsRequest.of(request)
paging_data = get_board_paged_posts(
search=board_posts_request.search,
board_urls=[board_url],
page=request.GET.get('page', 1)
)
page_posts = paging_data['page_posts']
has_previous = page_posts.has_previous()
has_next = page_posts.has_next()
return render(
...
)
이제 get_all_board_posts
를 만들어 봅시다.
def get_all_board_posts(request):
board_posts_request = BoardPostsRequest.of(request)
board_detail_display = '전체 게시판'
if board_posts_request.search:
board_detail_display = board_posts_request.search
paging_data = get_board_paged_posts(
search=board_posts_request.search,
page=request.GET.get('page', 1)
)
page_posts = paging_data['page_posts']
has_previous = page_posts.has_previous()
has_next = page_posts.has_next()
return render(
request,
'board/all_board_detail.html',
BoardPostsResponse(
board_detail_info=BoardDetailInfo(
name=board_detail_display,
info=board_detail_display,
url=board_detail_display,
),
posts=[
BoardPost(
id=post.id,
title=post.title,
short_body=post.short_body(),
board_url=post.board.url,
author_nickname=post.author.nickname,
created_at=post.created_at.strftime('%Y-%m-%d'),
like_count=post.like_count,
reply_count=post.reply_count,
image_url=post.post_img.url if post.post_img else static('logo.ico'),
) for post in page_posts
],
has_previous=has_previous,
has_next=has_next,
previous_page_number=page_posts.previous_page_number() if has_previous else None,
current_page_number=page_posts.number,
next_page_number=page_posts.next_page_number() if has_next else None,
last_page_number=page_posts.paginator.num_pages,
page_range=paging_data['page_range'],
).model_dump()
)
HTML
{% extends 'base.html' %}
{% load static %}
{% block style %}
<style>
.card_img{
background-repeat:no-repeat;
background-position-y:center;
background-size:contain;
}
.truncate-3 {
font-size: 15px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
</style>
{% endblock %}
{% block title %}{{board_detail_info.name}}{% endblock %}
{% block og_title %}{{board_detail_info.name}}{% endblock %}
{% block description %}{{board_detail_info.info}}{% endblock %}
{% block current_url %}https://cwbeany.com{{ request.get_full_path }}{% endblock %}
{% block img %}https://cwbeany.com/static/logo.ico{% endblock %}
{% block top %}
<div class="p-4 p-md-5 mb-3 rounded">
<div class="col-md-8 px-0">
<h3 class="display-4 font-monospace">{{board_detail_info.name}}</h3>
<p class="lead my-3 font-monospace">WHAT WE FOUND "{{ board_detail_info.name }}" LIST</p>
</div>
</div>
<!-- 글 목록 -->
<div class="row g-2 mb-4">
{% for post in posts %}
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<a class="text-decoration-none text-dark" href="{% url 'board:post' post.board_url post.id %}">
<div class="card">
<div class="row g-0">
<div class="col-lg-8">
<div class="card-body">
<h5 class="card-title" style="white-space:nowrap;overflow: hidden;text-overflow:ellipsis;">{{post.title}}</h5>
<p class="card-text truncate-3">{{post.short_body|striptags}}</p>
<div class="card-text"><small class="text-muted"><i class="bi bi-person-circle"></i> {{post.author_nickname}}</small></div>
<div class="card-text"><small class="text-muted"><i class="bi bi-calendar-week"></i> {{post.created_at}}</small></div>
<div>
<i class="bi bi-heart text-danger"></i></i> {{post.like_count}} <i class="bi bi-chat-right-text"></i> {{post.reply_count}}
</div>
</div>
</div>
<div class="col-lg-4 card_img d-none d-lg-block rounded" style="background-image:url({{post.image_url}});">
</div>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
<!-- 검색 하기 -->
<form class="d-flex mb-3" style="justify-content: flex-end;" method="get" action="">
<input class="me-2" type="text" value="{{ request.GET.search }}" name="search" placeholder="검색어를 입력하세요." />
<button class="btn btn-sm btn-primary" type="submit">검색</button>
</form>
<!-- 페이지 네이션 -->
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
{% if has_previous %}
<li class="page-item">
{% if request.GET.search %}
<a class="page-link" href="?page=1&search={{ request.GET.search }}" aria-label="First">
<span aria-hidden="true">«</span>
</a>
{% else %}
<a class="page-link" href="?page=1" aria-label="First">
<span aria-hidden="true">«</span>
</a>
{% endif %}
</li>
<li class="page-item">
{% if request.GET.search %}
<a class="page-link" href="?page={{ previous_page_number }}&search={{ request.GET.search }}" aria-label="Previous">
<span aria-hidden="true"><</span>
</a>
{% else %}
<a class="page-link" href="?page={{ previous_page_number }}" aria-label="Previous">
<span aria-hidden="true"><</span>
</a>
{% endif %}
</li>
{%endif%}
{% for i in page_range %}
{% if i == current_page_number %}
{% if request.GET.search %}
<li class="page-item active"><a class="page-link" href="?page={{i}}&search={{ request.GET.search }}">{{i}}</a></li>
{% else %}
<li class="page-item active"><a class="page-link" href="?page={{i}}">{{i}}</a></li>
{% endif %}
{% else %}
{% if "search=" in request.get_full_path %}
<li class="page-item"><a class="page-link" href="?page={{i}}&search={{ request.GET.search }}">{{i}}</a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{i}}">{{i}}</a></li>
{% endif %}
{% endif %}
{% endfor %}
{% if has_next %}
<li class="page-item">
{% if request.GET.search %}
<a class="page-link" href="?page={{ next_page_number }}&search={{ request.GET.search }}" aria-label="Next">
<span aria-hidden="true">></span>
</a>
{% else %}
<a class="page-link" href="?page={{ next_page_number }}" aria-label="Next">
<span aria-hidden="true">></span>
</a>
{% endif %}
</li>
<li class="page-item">
{% if request.GET.search %}
<a class="page-link" href="?page={{ last_page_number }}&search={{ request.GET.search }}" aria-label="Last">
<span aria-hidden="true">»</span>
</a>
{% else %}
<a class="page-link" href="?page={{ last_page_number }}" aria-label="Last">
<span aria-hidden="true">»</span>
</a>
{% endif %}
</li>
{%endif%}
</ul>
</nav>
{% endblock %}
짠~ 완성되었습니다!!
이제 검색할 때, 이 게시판으로 옮기도록 기존 코드를 바꿔야합니다.
board/templates/board/home.html
board:all_board_posts
로 바꿔줍니다..
{% extends 'base.html' %}
{% load static %}
{% block style %}
...
{% endblock %}
{% block middle_right %}
<!-- 검색 하기 -->
<form class="d-flex mb-3" style="justify-content: flex-end;" method="get" action="{% url 'board:all_board_posts' %}">
<input class="me-2" type="text" value="{{ request.GET.search }}" name="search" placeholder="검색어를 입력하세요." />
<button class="btn btn-sm btn-primary" type="submit">검색</button>
</form>
<!-- 소개 -->
...
<!-- Announce -->
...
<!-- Tags -->
...
{% endblock %}
검색을 하니 잘 이동합니다.