검색 기능 만들기
# board>views.py
from django.shortcuts import render
from board.models import Post
from django.core.paginator import Paginator
def board(request):
# 게시글 리스트
if request.method == "GET":
page = request.GET.get('page', 1)
search_text = request.GET.get('search_text', "")
post_set = Post.objects.filter(
title__icontains=search_text
).order_by('-id')
paginator = Paginator(post_set, 4)
post_set = paginator.get_page(page)
context = {
"post_set":post_set
}
return render(request, 'page/index.html', context=context)
확인을 위해 더미데이터 수정
<!-- templates/page/index.html -->
{% extends 'common/base.html' %}
{% block content %}
<div class="row">
<div class="col">
<div class="input-group">
<input type="text" name="search_text" />
<button class="btn btn-outline-secondary">검색</button>
</div>
</div>
...
<!-- templates/page/index.html -->
{% extends 'common/base.html' %}
{% block content %}
<div class="row">
<div class="col">
<form method="get">
<div class="input-group">
<input type="text" name="search_text" />
<button type="submit" class="btn btn-outline-secondary">
검색
</button>
</div>
</form>
</div>
</div>
이전글, 다음글 시에도 적용
# board>views.py
...
context = {
"post_set":post_set,
"search_text":search_text,
}
...
<!-- templates/page/index.html -->
<!-- input에서 search_count로 미리 세팅 + 아래 href에 search_text 추가 -->
{% extends 'common/base.html' %}
{% block content %}
<div class="row">
<div class="col">
<form method="get">
<div class="input-group">
<input type="text" name="search_text" value="{{ search_text }}"/>
<button type="submit" class="btn btn-outline-secondary">
검색
</button>
</div>
</form>
</div>
</div>
<div class="row">
<div class="row">
{% for post in post_set %}
<div class="col-6 p-2">
<div class="card">
<div class="card-body">
<h5>{{ post.title }}</h5>
<p>{{ post.content }}</p>
<p>
{{ post.user.nickname }}
<small>{{ post.reg_date|date:"Y-m-d" }}</small>
</p>
<p>{{ post.comment_set.all.count }}</p>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="row mt-4">
<div class="col-4 text-start">
{% if post_set.has_previous %}
<a
class="text-decoration-none fs-5"
style="font-weight: bold; color: black"
href="{% url 'board' %}?page={{ post_set.previous_page_number }}&search_text={{ search_text }}"
>이전글</a
>
{% endif %}
</div>
<div class="col-4 text-center">
{{ post_set.number }}/{{ post_set.paginator.num_pages }}
</div>
<div class="col-4 text-end">
{%if post_set.has_next %}
<a
class="text-decoration-none fs-5"
style="font-weight: bold; color: black"
href="{% url 'board' %}?page={{ post_set.next_page_number }}&search_text={{ search_text }}"
>다음글</a
>
{% endif %}
</div>
</div>
{% endblock %}
</div>
페이징 기준 변경(2개씩)
# board>views.py
...
paginator = Paginator(post_set, 2)
...
모양 다듬기
<!-- templates/page/index.html -->
...
<div class="input-group">
<input class="form-control" type="text" name="search_text" value="{{ search_text }}"/>
<button type="submit" class="btn btn-outline-secondary">
검색
</button>
</div>
...
<!-- templates/common/base.html -->
<html>
<head>
<title>Anonymous</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
{% include "component/nav.html" %}
<div class="container" style="max-width: 760px;padding: 40px 16px;">
{% block content %}
{%endblock %}
</div>
{% include "component/footer.html" %}
</body>
</html>
모바일 환경에도 적합할 수 있게 수정
<!-- templates/common/base.html -->
<html>
<head>
<meta name="viewport" content="width=divice-width,initial-scale=1.0">
<title>Anonymous</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
{% include "component/nav.html" %}
<div class="container" style="max-width: 760px;padding: 40px 16px;">
{% block content %}
{%endblock %}
</div>
{% include "component/footer.html" %}
</body>
</html>
<!-- templates/component/nav.html -->
<div class="row text-center border-bottom align-items-center" style="width: 100%;margin:0">
<div class="col">
<a class="text-decoration-none fs-1"
style="font-weight: bold;color: #999999;"
href="{% url 'board' %}"
>Anonymous</a>
</div>
<div class="col">
{% if request.user.is_authenticated %}
<p class="m-0">{{ request.user.nickname }}</p>
<a class="text-decoration-none fs-5"
style="font-weight: bold;color: #C60000;">글쓰기</a>
<a class="text-decoration-none fs-5"
style="font-weight: bold;color: black;"
href="{% url 'signout' %}"
>로그아웃</a>
{% else %}
<a class="text-decoration-none fs-5"
style="font-weight: bold;color: black;"
href="{% url 'signin' %}"
>로그인</a>
{% endif %}
</div>
</div>
오늘은 게시판 리스트 로직의 검색 기능을 프론트엔드와 백엔드로 나누어 한번에 구현했다.
강의를 거의 Mac으로 듣다가, 오늘은 Windows로 사용하기 위해 서버를 run했는데, 아무 내용이 나오지 않아 잠시 당황했었다.
하지만 환경이 바뀌어 어제 넣었던 더미 데이터를 지금 쓰려는 컴퓨터가 인식하지 못하는 것은 당연했다.
코드 상에 자동 주입이 되도록 썼다면 서버를 켜는 순간 DB에 접근해서 테이블과 데이터를 모두 넣었겠지만, 이 경우는 그렇지 않기 때문이다.
그동안 JPA를 사용하고, Update 속성을 사용하면서 서버를 켜기만 해도 DB 설정이 자동으로 주입되는 구현을 오랫동안 해왔고 그것에 적응하니 이렇게 간단하지만 문제가 생기는 상황도 발생한 것 같다.
에러를 해결하고 난 뒤, 검색 기능의 개발을 위해 동일한 내용으로 적어두었던 더미 데이터의 내용을 조금씩 다르게 수정해준 다음 백엔드의 검색 기능에 해당하는 search_text를 get으로 불러오도록 로직을 구현했다.
그 다음, 프론트에 bootstrap의 input-group 클래스를 사용해 검색 창을 만들었다.
그리고 마지막으로 페이징하는 이전글, 다음글에서도 검색값이 동일하게 적용된 상태에서 넘어갈 수 있도록 href에 search_text를 추가해줬으며 디자인을 수정해 모바일에서도 잘 볼 수 있도록 했다.
검색 기능은 여러 프로젝트에서 기본적인 기능으로 생각되지만, 그렇다고 해서 다양한 조건에 따른 검색 기준을 따로 설정한다던지, 검색을 동적으로 할 것인지 등을 고려한 적은 없었던 것 같다.
django로 빠르게 검색 기능을 만들 수 있으니 이 부분을 나중에라도 고려해서 검색 기능을 고도화하고 싶다는 생각이 드는 강의였다.