🏦

14. 템플릿 적용 및 검색 기능 구현

템플릿 가져오기

이제 전에 들었던 수업의 UI를 Django에 입히는 작업이 남아 있습니다. 우선 아래 링크에서 파일을 다운로드 받아 아래처럼 수행해주세요.
💡
3.1 Version의 코드와 3.2 Version에 코드 차이는 없으니 그대로 사용하셔도 됩니다.
 
파일을 다운 받으시면 static 폴더와 templates 폴더가 있습니다. 이를 main 폴더 아래에 넣어줍니다.
  • 우클릭 하여 ‘파일 가져오기/업로드’ 버튼을 누르신 다음 파일을 선택하셔서 업로드하시면 됩니다.
 
notion imagenotion image

템플릿 상속

이번에는 템플릿 상속에 대해 알아보도록 하겠습니다. 예를 들어 메뉴바가 바뀌었다 가정한다면, 그동안 편집해두었던 .html파일을 모두 수정해야 하는 상황이 발생됩니다.
이러한 상황을 막기 위해 Django에서는 템플릿 상속을 지원합니다. 하나의 템플릿을 만들어 여러 개의 템플릿에서 상속받을 수 있도록 하는 것이죠. 위에서 들었던 예로, 메뉴를 하나의 템플릿으로 만들어 다른 파일이 상속할 수 있게 한다면 단 1개의 파일, 메뉴 파일만 수정하면 됩니다.
 
내용 {% block content %} {% endblock %} 내용
상속할 템플릿
{% extends "main/base.html" %} {% block content %} 내용 {% endblock content %}
상속받을 템플릿
 

about 페이지

이번에는 about page를 만들어 보도록 하겠습니다.
  1. about.html 파일 URL 연결
  1. write.html 파일 URL 연결
이제 좀 익숙하시죠? 😉 익숙하시니! 지난번에 언급해드린 것처럼, 다른 코드를 조금 수정하도록 하겠습니다.
 
urls.py
from django.contrib import admin from django.urls import path from main.views import index, about, cafelist, cafedetails from django.conf.urls.static import static from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('', index, name='index'), path('about/', about, name='about'), path('cafelist/', cafelist, name='cafelist'), path('cafelist/<int:pk>', cafedetails, name='cafedetails'), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
추가된 path 말고도, 다른 path들에 name 속성이 붙었죠? 이렇게 하면 지난번에 한 것처럼 URL을 하드코딩하는 것이 아니라, URL이 변경되어도 아래처럼 유동적으로 사용할 수 있답니다.
<a href="{% url 'index' %}">클릭하세요!</a>
 
어때요? 훨씬 편하죠? 하지만 처음에는 익숙하지 않으실 테니, 천천히 바꿔 가십시오.
 
views.py
from django.shortcuts import render from .models import Cafe def index(request): context = { 'locations' : Cafe.locations } return render(request, 'main/index.html', context) def about(request): return render(request, 'main/about.html')
notion imagenotion image
 
 

선택 지역 카페 리스트 보여주기

index 페이지에서 다음 사진과 같이 지역을 선택해서 카페 리스트를 볼 수 있도록 화면을 구성하려고 합니다.
notion imagenotion image
그러려면 index 페이지에 제주 지역들의 리스트의 정보를 전달해 주어야 합니다.
from django.shortcuts import render from .models import Cafe def index(request): context = { 'locations' : Cafe.locations } return render(request, 'main/index.html', context)
 
이렇게 지역 정보를 locations라는 이름으로 index.html에 넘겨주면 index.html의 다음 for 태그를 이용해 지역 이름들이 렌더링 됩니다.
{% for location in locations %} <div class="jejumap-item" id="jejumap-item-hangyeong"> <input type="checkbox" class="jejumap-check te-elem" id="check-area-{{ forloop.counter }}" data-city="notJcity" name='locations' value='{{ location.0 }}'> <div class="mapshape"></div> <label class="jejumap-item-title te-elem" for="check-area-{{ forloop.counter }}">{{ location.1 }}</label> </div> {% endfor %}
 
이제 index 페이지에서 지역을 선택하면 선택된 지역의 카페들만 보여지도록 cafelist 함수를 다음과 같이 수정합니다.
def cafelist(request): selected_locations = request.GET.getlist('locations') if selected_locations: cafes = Cafe.objects.filter(location__in=selected_locations) else: cafes = Cafe.objects.all() context = { 'cafes': cafes } return render(request, 'main/cafelist.html', context)
  • Cafe.objects.filter(location__in=selected_locations) 이 부분의 의미는 location 값이 selected_location에 포함되는 카페들만 필터링하겠다는 의미입니다.
 
이제 제주시만 선택한 후 카페찾기를 누르면 제주시 카페만 나옵니다.
notion imagenotion image
 
notion imagenotion image
 
 

카페 이름 검색기능 구현

notion imagenotion image
메뉴 바의 검색창에 카페 이름을 검색하면 해당 이름과 관련된 카페들의 리스트를 볼 수 있도록 합니다. cafelist 함수를 수정합니다.
 
def cafelist(request): selected_locations = request.GET.getlist('locations') search = request.GET.get('search') if selected_locations: cafes = Cafe.objects.filter(location__in=selected_locations) elif search: cafes = Cafe.objects.filter(name__icontains=search) else: cafes = Cafe.objects.all() context = { 'cafes': cafes } return render(request, 'main/cafelist.html', context)
  • Cafe.objects.filter(name__icontains=search) 이 부분의 의미는 카페의 name이 검색어 search를 포함하고 있는 카페들만 필터링하겠다는 의미입니다.
 
이제 2 를 검색하면, 2와 연관된 이름을 갖는 cafename2만 검색됩니다.
notion imagenotion image
 
notion imagenotion image