각 애플리케이션의 첫 페이지들은 만들었지만 프로젝트의 첫 페이지인 루트(/) URL에 대한 처리 로직은 아직 개발하지 못한 상태
네비게이션 항목 중 [Project_Home] 항목을 클릭했을 때 에러가 발생한 이유가 프로젝트 첫 페이지인 루트(/) URL에 대한 처리 로직이 없기 때문이다.
로직 설계
UI 설계
테이블은 변경사항이 없으므로 모델 코딩은 필요 없다.
애플리케이션에 대한 URL이 아닌 프로젝트에 대한 URL이므로 testsite/urls.py 파일에 루트(/) URL 및 임포트 문장, 두 줄만 추가하면 된다.
path('', views.HomeView.as_view(), name='home'),
앞에서 정의한 HomeView 코딩. 프로젝트와 관련된 뷰이므로 testsite/views.py 파일에 코딩한다.
from django.views.generic import TemplateView
# TemplateView
class HomeView(TemplateView):
# TemplateView 제네릭 뷰를 상속받을 경우 template_name 필수
# 템플릿 파일이 위치하는 디렉토리는 settings.py 파일의
# TEMPLATES 항목에 리스트 요소로 추가되어 있다.
template_name = 'home.html'
# 템플릿 시스템으로 넘겨줄 컨텍스트 변수는
# get_context_data() 메소드를 오버라이딩해서 정의
def get_context_data(self, **kwargs):
# get_context_data() 메소드 정의시 super() 메소드 호출 필수
context = super().get_context_data(**kwargs)
# testsite 프로젝트 하위에 있는 애플리케이션들의 리스트들을
# 보여주기 위해 컨텍스트 변수 app_list에 담아서
# 템플릿 시스템에 넘겨준다.
context['app_list'] = ['polls', 'books']
return context
home.html 템플릿은 프로젝트 템플릿이므로 상속에 사용하는 부모 템플릿의 위치와 동일한 디렉토리에 생성
{% extends 'base_books.html %}
{% block content %}
<h2>shkim Django Application</h2>
<ul>
{% for appname in app_list %}
{% with appname|add:":"|add:"index" as urlvar %}
<li><a href="{% url urlvar %}">{{ appname }}</a></li>
{% endwith %}
{% endfor%}
</ul>
{% endblock content %}
뷰로부터 app_list 컨텍스트 변수를 전달받아 app_list에 있는 appname들을 하나씩 순회하면서 화면에 보여준다.
애플리케이션명을 클릭 시 접속할 URL을 추출하기 위해 {% url urlvar %} 태그를 사용했고, urlvar 인자는 {% with %} 태그를 사용해 정의한다.
예를 들어, 애플리케이션명이 books라면 urlvar는 books:index가 된다.
프로젝트의 전반적인 항목들을 설정하는 곳 : settings.py
각 앱마다 필요한 항목을 설정하는 곳 : apps.py
앱의 별칭을 부여하는 예제를 통해 apps.py 파일 기능 활용하기
books/apps.py 파일 수정
...
class BooksConfig(AppConfig):
...
verbose_name = 'Book-Author-Publisher App'
books 앱의 설정 클래스인 BooksConfig의 속성 중 하나인 verbose_name을 정의했다.
testsite/views.py 파일 수정
...
def get_context_data(self, **kwargs):
...
# 이 라인 대신 아래 5라인 추가
# context['app_list'] = ['voting', 'books']
dictVerbose = {}
# apps 객체의 get_app_configs() 메소드를 호출하면
# settings.py 파일의 INSTALLED_APPS에 등록된
# 각 앱의 설정 클래스들을 담은 리스트를 반환
for app in apps.get_app_configs():
# app.path는 각 설정 클래스의 path 속성으로
# 애플리케이션의 물리적 경로를 뜻한다.
# site-packages 문자열이 있으면 외부 앱이므로 제거
if 'site-packages' not in app.path:
# 설정 클래스의 label 속성값을 key로
# verbose_name 속성값을 value로 해서 dicVerbose 사전에 등록
dictVerbose[app.label] = app.verbose_name
# verbose_dict 컨텍스트 변수에 dictVerbose 사전 대입
context['verbose_dict'] = dictVerbose
return context
tempaltes/home.html 수정
...
<!-- ul 부분을 수정 -->
<ul>
{% for key, value in verbose_dict.items %}
<li><a href="{% url key|add:':index' %}">{{ value }}</a></li>
{% endfor%}
</ul>
{% endblock content %}
뷰로부터 전달받은 컨텍스트 변수 verbose_dict 사전을 순회하기 위해 items() 메소드를 호출한다.
key : 설정 클래스의 label 속성값
value : 설정 클래스의 verbose_name 속성값
출처: Django로 배우는 파이썬 웹 프로그래밍(기초) - 김석훈님