DetailView

Jeong Ha Seung·2021년 11월 25일

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
profile
블로그 이전했습니다. https://morethan-haseung-log.vercel.app

0개의 댓글