| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준
- channels
- js
- Class
- 개발일지
- Git
- 장고
- re-id
- 1주차
- vscode
- sql
- 마스킹
- 파이썬
- 정보처리기사
- 2주차
- 미니프로젝트
- WIL
- 채팅
- poetry
- Commpot
- REDIS
- 정보처리기사실기
- github
- 가상환경
- WebSocket
- 알고리즘
- resnet50
- 프로그래머스
- WHERE절
- 프로젝트
Archives
- Today
- Total
개발일기
검색기능 구현하기 본문
그럼 이제 검색기능을 구현해보자!
검색 기능의 아이디어는, 검색키워드를 받고 그 키워드가 담겨있는 게시글을 보여주거나,
키워드를 가진 게시글이 없다면 혹은 검색어를 입력하지 않은 경우에는 메세지를 띄워주는 것으로 구현을 했다.
구체적으로 코드를 보면서 어떻게 구현했는지 살펴보자.
<post views.py>
def search(request):
if request.method == 'GET':
searched = request.GET.get("searched","")
posts = Posting.objects.filter(content__contains=searched).order_by('-created_at')
if posts.exists() == False:
return render(request, 'posting/searched.html', {'searched': searched, 'error': "찾으시는 검색어를 가진 글은 존재하지 않습니다."})
count = posts.count()
page = int(request.GET.get('page','1'))
paginator = Paginator(posts,5)
post_list = paginator.get_page(page)
return render(request, 'posting/searched.html', {'searched': searched, "post_list": post_list, 'count':count})
else:
return render(request, 'posting/searched.html', {})
<코드 자세히 살펴보기>
- posts = Posting.objects.filter(content__contains=searched).order_by('-created_at')
- 최신순으로 정렬되면서, content__contains=searched의 의미는, 게시글에 검색어가 포함되어있을 경우 가지고오라는 의미이다.
- if posts.exists() == False: 만약 검색결과가 존재하지 않는다면, 에러메세지를 보여주었다.
- count = posts.count() : 검색결과의 개수를 세서 보여주었다.
- 검색결과를 보여주는 페이지 역시 페이징을 써서 한 페이지 당 5개의 게시글을 보여주도록 코드를 짰다.
- 페이징과 관련되어서는 이전 글을 참고해주길 바란다!
<base.html>
<form class="d-flex" method="GET" action="{% url 'search' %}">
{% comment %} {% csrf_token %} {% endcomment %}
<input class="form-control me-sm-2" type="search" placeholder="Search" name="searched" aria-label="Search">
<button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
</form>
<searched html>
{% if searched %}
{% if error %}
<div class="alert alert-danger" role="alert">{{ error }}</div>
{% else %}
<h4> 검색하신 {{ searched }} 정보입니다. 총 {{count}}개의 검색결과가 있습니다.</h4>
<p></p>
{% for ps in post_list %}
<div class="col-md-12 mb-2">
<div class="card">
<div class="card-body">
{% if user == ps.author or user.is_superuser %}
<div style="text-align: right">
<a href="/api/posts/delete/{{ ps.id }}">
<span class="badge rounded-pill bg-danger">삭제</span>
</a>
</div>
{% endif %}
<div style="text-align: right">
<a href="/api/posts/{{ ps.id }}">
<span class="badge rounded-pill bg-success">보기</span>
</a>
</div>
<div class="media">
<div class="media-body">
<h5 class="mt-0">Title: {{ ps.title }}</h5>
<p>{{ ps.content|slice:":15"}}...</p>
<p>Category: {{ ps.category }}</p>
</div>
<div style="text-align: right">
<span style="font-size: small">{{ ps.author_name }}-{{ ps.created_at|timesince }} 전</span>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
<!--페이징 처리 코드는 생략-->
{% endif %}
{% else %}
<h3> 검색어를 입력해주세요. </h3>
{% endif %}
<코드 자세히 살펴보기>
- {% if searched %} 검색어가 있다면
- {% else %} 검색어가 없다면<h3> 검색어를 입력해주세요. </h3>
- 검색어가 있지만 검색결과가 없을 경우 {{error}} 를 보여준다.
- views.py 참고: {'searched': searched, 'error': "찾으시는 검색어를 가진 글은 존재하지 않습니다."})
- 만약 로그인한 사용자와 글쓴이가 같을 경우, 혹은 관리자일 경우, 삭제가 가능하게 했다.
{% if user == ps.author or user.is_superuser %}
<div style="text-align: right">
<a href="/api/posts/delete/{{ ps.id }}">
<span class="badge rounded-pill bg-danger">삭제</span>
</a>
</div>
{% endif %}
- 게시글은, 제목과 글 내용, 카테고리, 저자, 시간이 보이도록 했다.
- 이때 글 내용은 15자까지만 보이도록 slice문을 추가했다.
<h5 class="mt-0">Title: {{ ps.title }}</h5>
<p>{{ ps.content|slice:":15"}}...</p>
<p>Category: {{ ps.category }}</p>
검색기능을 하면서 고민했던 부분은, 검색결과를 유지하면서 어떻게 페이징을 구현할 수 있을까 하는 부분이었다.
원래는 검색기능을 post 메서드로 구현했었는데, 페이징과 함께 구현을 하려고 하다보니 get 메소드로 바꾸게 되었다.
get 메소드로 할 경우 쿼리 파라미터로 구현할 수 있기 때문에, 페이지를 넘기더라도 검색결과가 유지될 수 있다.
<div style="text-align:center">
<ul class="pagination">
<div style="width:35%; margin: 5px;">
{% if post_list.has_previous %}
<a class="abutton" href="?searched={{request.GET.searched}}&page=1">맨 앞으로</a>
<a class="abutton" href="?searched={{request.GET.searched}}&page={{ post_list.previous_page_number }}">이전</a>
{% endif %}
</div>
<div style="width:30%; margin: 5px;">
{% for page in post_list.paginator.page_range %}
{% if page >= post_list.number|add:-2 and page <= post_list.number|add:2 %}
<span class="{% if page == post_list.number %}current{% endif %}">
<a href="?searched={{request.GET.searched}}&page={{ page }}">{{ page }}</a>
</span>
{% elif page >= post_list.number|add:-3 and page <= post_list.number|add:3 %}
..
{% endif %}
{% endfor %}
</div>
<div style="width:35%; margin: 5px;">
{% if post_list.has_next %}
<a class="abutton" href="?searched={{request.GET.searched}}&page={{ post_list.next_page_number }}">다음</a>
<a class="abutton" href="?searched={{request.GET.searched}}&page={{ post_list.paginator.num_pages }}">맨 뒤로</a>
{% endif %}
</div>
</ul>
</div>
<코드 자세히 살펴보기>
- <a class="abutton" href="?searched={{request.GET.searched}}&page=1">
- 검색어를 유지하면서 페이징을 구현할 수 있다.
- 나머지 코드들은 페이징 구현하기 이전 게시글에서 충분히 설명했기 때문에 설명을 생략하도록 하겠다.
<Result>
- 검색결과가 없을 때

- 검색결과가 있을 때

- 검색어가 없을 때

- 로그인한 유저가 쓴 글이 검색결과에 있을 때 (삭제 버튼이 보인다.)

'Project Portfolio' 카테고리의 다른 글
| 장고 조회수 기능 구현하기 (0) | 2023.05.09 |
|---|---|
| 이름 미정 새로운 프로젝트~ (2) | 2023.05.08 |
| 페이징(pagination) 구현하기 (0) | 2023.04.14 |
| 게시글 수정하기 기능(모달과 페이지 두 가지 버전으로 만들기) (0) | 2023.04.13 |
| 게시글 자세히보기/삭제하기/댓글 작성하기/삭제하기 기능 (0) | 2023.04.13 |