HomeView 관련 포스팅을 해놓고 DetailView와 SearchView(다음 글에 쓸 예정)은 안해서 지금 쓴다.
1)url dispatcher
url dispatcher는 url에 변수를 담을 수 있게 해준다. str,int,path 등으로 url 값을 변환하여 view로 전달해준다.
rooms/urls.py
from django.urls import path from . import views app_name = "rooms" #꼭 추가해줘야 한다. urlpatterns = [path("<int:pk>", views.room_detail, name="detail")]
config/urls.py
urlpatterns = [ path("", include("core.urls", namespace="core")), path("rooms/", include("rooms.urls", namespace="rooms")), #다음과 같이 추가한다. path("admin/", admin.site.urls), ]
templates/partials/header.html
<header> <a href="{% url 'core:home %}">Nbnb</a> <ul> <li><a href="#">Login</a></li> </ul> </header>
templates/rooms/room_list.html
{% extends "base.html" %} {% block page_name %} Home {% endblock page_name %} {% block content %} {{now}} {% for room in rooms %} <h3> <a href="{% url "rooms:detail" room.pk %}"> {{room.name}} / ${{room.price}} </a> #name,namespace를 이용하여 room에 대한 pk를 바로 알아낼 수 있다. #config/urls.py 파일에서 namespace=rooms, rooms/urls.py 내 name=detail이 추가되었으므로 #room_list.html 파일에서 url 태그 내에 "rooms:detail"이라고 쓸 수 있다. </h3> {% endfor %} <h5> {% if page_obj.has_previous %} <a href="?page=>{{page_obj.previous_page_number}}">Pre> vious</a> {% endif %} Page {{page_obj.number}} of {{page_obj.paginator.num_pages}} {% if page_obj.has_next %} <a href="?page= {{page_obj.next_page_number}}">Next</a> {% endif %} </h5> {% endblock content %}
rooms/views.py
from django.views.generic import ListView from django.shortcuts import render from . import models class HomeView(ListView): """ HomeView Definition """ model = models.Room paginate_by = 10 paginate_orphans = 5 ordering = "created" context_object_name = "rooms" def room_detail(request, pk): print(pk) #pk 값 출력 return render(request, "rooms/detail.html")
2)get_absolute_url
model이 웹사이트에서는 어떻게 보여야 할까
수동적으로는 rooms/id 이런식으로 쳐야 한다.
하지만 Django의 도움을 받으면 편리하게 할 수 있다.
바로 get_absolute_url이라는 놈이
내가 원하는 model을 찾을 수 있는 url을 제공해준다.
rooms/models.py
from django.urls import reverse ... def get_absolute_url(self): return reverse("rooms:detail", kwargs={"pk": self.pk}) # reverse("[namespace값]:[name값]", kwargs={"pk": self.pk})
rooms/views.py
from django.urls import reverse from django.shortcuts import render, redirect ... try: room = models.Room.objects.get(pk=pk) return render(request, "rooms/detail.html", {"room": room}) except models.Room.DoesNotExist: #존재하지 않는 pk로 접근할 경우 return redirect(reverse("core:home")
templates/rooms/detail.html
{% extends "base.html" %} {% block page_name %} Home {% endblock page_name %} {% block content %} <div> <h1>{{room.name}}</h1> <h3>{{room.description}}</h3> </div> <div> <h2>By: {{room.host.username}} #ForeignKey로 host 표시 {% if room.host.superhost %} (superhost) {% endif %} </h2> <h3>Amenities</h3> <ul> {% for a in room.amenities.all %} # ManyToManyField 사용 <li>{{a}}</li> {% endfor %} </ul> <h3>Facilities</h3> <ul> {% for a in room.facilities.all %} # ManyToManyField 사용 <li>{{a}}</li> {% endfor %} </ul> <h3>House Rules</h3> <ul> {% for a in room.house_rules.all %} # ManyToManyField 사용 <li>{{a}}</li> {% endfor %} </ul> </div> {% endblock %}
Template에서도 Foreign Key와 ManyToMany Field를 사용할 수 있다.
CBV로 구현
지금까지 FBV로 상세페이지를 구현했다면 지금은 CBV로 구현해보려 한다.
rooms/urls.py
urlpatterns = [path("<int:pk>", views.RoomDetail.as_view(), name="detail")]
rooms/views.py
from django.views.generic import ListView, DetailView ... class RoomDetail(DetailView): """RoomDetail Definition""" model = models.Room