사실 한 가지 프로그래밍하지 않은 페이지가 있는데
바로 All authors 페이지를 프로그래밍 하지 않았다.
이번 도전 과제는
이 All authors 페이지가 정상적으로 작동하도록
프로그래밍 하는 것이다.
정확히는 All authors를 눌렀을 때
실제 화면에 표시되는 Template와
데이터를 Model로 부터 받아오는 View를 프로그래밍하면 된다.
기능 상으로는 All authors페이지와 똑같기 때문에
변수 명만 바꿔주면 될 것 같다.
먼저 작가 목록을 보여줄 페이지 부터 해보자.
위의 화면은 All books 하이퍼링크를 누르면 나오는 화면이다.
대충 Book List를 Authors List으로
아래의 책 이름을 저자 이름으로
보이게끔 하면 될 것 같다.
대충 그림은 그려졌으니
실제로 프로그래밍 해보자.
먼저 book_list.html 파일을 복사해 붙여 넣기 후
author_list.html으로 이름을 바꾸자.
수정할 곳이 몇몇 보일 것 이다.
그 중 가장 중요한 book.get_absolute_url 쪽(9번째 줄)을 보면
이 메소드는 Model을 작성했을 때
동적 url을 리턴하는 메소드였는데
위와 같이 Author Model에서도
똑같이 get_absolute_url이라는 메소드를
작성했던 것을 기억날 것이다.
똑같이 이것을 사용해 template를 작성해보기 전에
ListView와 DetailView를 먼저 코딩하고,
url을 이어줘야 한다.
먼저 View에 제너릭 뷰를 추가해보자.
class AuthorListView(generic.ListView):
model = Author
paginate_by = 5
class AuthorDetailView(generic.DetailView) :
model = Author
위와 같이 ListView와 DetailViwe를 생성하고
녹색 박스와 같이 pagination(페이징)을 해준다.
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
path('author/', views.AuthorListView.as_view(), name='authors'),
path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
]
그리고 정의했던
AuthorListView와 AuthorDetailView의 url을 정의하자.
다음에는 하이퍼링크를 누르면 이동하게끔
base_genric.html파일에 코드를 추가해주어야 한다.
여기서 authors라는 이름은
path() 함수에 정의 했을때
name 인수에 정의했던 데이터를 코딩하면 된다.
나는 위에서 path( ... , ... , name = 'authors')로 했기 때문에
authors로 코딩했다.
그 다음 처음에 복사하고
이름만 바꿨던 author_list.html 파일을 수정해보자.
{% extends "base_generic.html" %}
{% block content %}
<h1>author List</h1>
{% if author_list %}
<ul>
{% for author in author_list %}
<li>
<a href="{{ author.get_absolute_url }}">{{ author }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>There are author in the library.</p>
{% endif %}
{% endblock %}
코드를 보면 알겠지만
놀랍게도 내가 한것이라고는 이름만 바꿨을 뿐이다.
다만, 빨간색 박스에서 author만 코딩한 이유는
Model을 정의 했을 때 __str__ 메소드를
작가의 first name과 second name을 합쳐서 보이게 끔
코딩한 적이 있는데
Author Model은 아래와 같다.
이 __str__ 메소드는 객체만 호출됐을 때
호출되는 메소드이다.
따라서 객체만 달랑 코딩해놓으면 자동적으로
__str__ 메소드가 불려오고,
그에 따른 리턴값이 나올 것이다.
왼쪽이 book_list.html 파일이고,
오른쪽이 author_list.html 파일 이다.
나는 정말로 이름만 바꾸었다.
거짓말이 아니다.
이제 브라우저에 All authors 하이퍼링크를 클릭하면
작가들의 목록이 나오는 것을 확인해 볼 수 있다.
다음으로 DetailView로 넘어가보자.
ListView때와 마찬가지로
book_detail.html을 복사해 붙여넣고
이름을 author_detail.html으로 바꿔보자.
우리가 할 일을 크게 2가지 이다.
빨간색 박스 와 같이 Author의 레코드를 나열하고,
녹색 박스와 같이 해당 작가의 책을 출력할 것이다.
그럼 먼저 빨간색 박스부터 해보자.
Author Model을 살펴보면
우리가 표시해야될 레코드는 3가지 인 것을 알 수 있다.
물론 변수는 4개가 정의되어있다.
하지만 이름은 합쳐서 불러올 것이기 때문에
3가지만 설정하면 될 것이다.
위에서 설명했듯이
3개의 레코드만 출력하면 되기 때문에
3줄을 코딩해준다.
{% extends "base_generic.html" %}
{% block content %}
<h1>Name : {{ author }}</h1>
<p><strong>Birth Date : </strong> {{ author.date_of_birth }}</p>
<p><strong>Death Date : </strong> {{ author.date_of_death }}</p>
<div style="margin-left:20px;margin-top:20px">
<h4>Copies</h4>
{% for copy in book.bookinstance_set.all %}
<hr>
<p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">{{ copy.get_status_display }}</p>
{% if copy.status != 'a' %}
<p><strong>Due to be returned:</strong> {{copy.due_back}}</p>
{% endif %}
<p><strong>Imprint:</strong> {{copy.imprint}}</p>
<p class="text-muted"><strong>Id:</strong> {{copy.id}}</p>
{% endfor %}
</div>
{% endblock %}
굵게 표시한 코드가 실제 수정된 코드이다.
이제 저장하고 실제 출력되는
화면을 확인해보자.
프로그래밍 한 대로 이름, 출생일, 사망일이 표시 된다.
다음은 녹색 박스다.
우리가 하고 싶은것은 위의 Copies아래에
해당 작가의 책의 레코드를 나타내고 싶다.
<div style="margin-left:20px;margin-top:20px">
<h4>Author BookList</h4>
{% for copy in author.book_set.all %}
<hr>
<p><strong>Title:</strong> {{copy.title }}</p>
<p><strong>Summary:</strong> {{copy.summary | linebreaks}}</p>
<p><strong>ISBN:</strong> {{copy.isbn}}</p>
<p><strong>Genre:</strong> {{copy.genre.all.get}}</p>
<p><strong>Language:</strong> {{copy.language}}</p>
<p class="text-muted"><strong>Id:</strong> {{copy.id}}</p>
{% endfor %}
</div>
작가의 관련 책들을 나타내는 코드는 위와 같다.
기존 book_dateil.html을 참고하여
author.book_set.all의 객체를
copy 변수에 집어넣어 데이터들을 출력했다.
다만 하늘색 박스와 같이 처음 나오는 코드들이 있다.
먼저 linebreaks은 일반 텍스트의 줄 바꿈을
적절한 HTML로 바꿔주는 태그이다.
book Model의 summary는
위의 사진과 같이 TextField 타입인데
그대로 표시할 경우 줄바꿈 형태가 없이 출력이 된다.
따라서 linebreaks 태그를 사용해서 줄바꿈을 해주어야 한다.
자세한 사항은 아래의 링크
공식 도큐먼트를 참고하기 바란다.
그 다음으로
copy.genre.all.get을 하는 이유는
위의 사진과 같이 genre가
다대다 타입의 필드(ManyToManyField)이기 때문이다.
copy.genre.all로 불러오게 되면
위와 같이 QureySet이 표시되기 때문에
get() 메소드를 사용해서 데이터만 불러온다면
깔끔하게 데이터만 가져올 수 있다.
이처럼 올바르게 프로그래밍 했다면
아래와 같은 화면을 볼 수 있다.
이 정도 했으면
도전 과제는 무사히 완수했다고 볼 수 있을 것 같다.