Djangoでbase.htmlにデータを渡す方法
Djangoでbase.htmlにデータを渡す方法をご紹介します。
条件
- Django 2.1.3
- Python 3.7.0
実現する内容
Djangoでテンプレートを実装する際、ナビゲーションバーなど共通で使用するものは「base.html」として共通化して、各ページで{% extends ‘base.html’ %}してテンプレートを拡張する手段が用いられます。
https://tutorial.djangogirls.org/ja/template_extending/
ここでは、base.htmlに特定の情報を渡すことで、ページごとにナビゲーションバーの表示を切り替えてみたいと思います。
具体的には以下の通りです。
- 一覧画面では、ナビゲーションバーの特定リンクを表示しない。
- 詳細画面では、ナビゲーションバーの特定リンクを表示する。
実現方法
詳細画面のviewで「def get_context_data(self, **kwargs):」を定義することにより、テンプレートへデータを渡します。
views.py
ここでは「my_model_pk」という変数を定義し、MyModelのpkを渡しています。
# 一覧画面 class IndexView(LoginRequiredMixin, generic.ListView): model = MyModel paginate_by = 5 ordering = ['-updated_at'] template_name = 'monitor/index.html' # 詳細画面 class DetailView(LoginRequiredMixin, generic.DetailView): model = MyModel template_name = 'monitor/detail.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['my_model_pk'] = self.kwargs['pk'] return context
base.html
{% if my_model_pk %}{% endif %}によって、my_model_pkという変数が存在した場合のみ、ナビゲーションバーに「グラフ」というメニューが表示されるようになります。
すなわち、一覧画面では「グラフ」は表示されず、詳細画面では「グラフ」がナビゲーションバーに表示されます。
<!-- base.html抜粋 --> <body> <main> <!-- ナビゲーションバーの設定 --> <nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top"> <div class="container"> <a class="navbar-brand" href="{% url 'monitor:index' %}">温室監視サービス</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarResponsive"> <ul class="navbar-nav ml-auto"> {% if user.is_authenticated %} <li class="nav-item"> <a class="nav-link" href="{% url 'monitor:index' %}">TOP</a> </li> {% if my_model_pk %} <li class="nav-item"> <a class="nav-link" href="{% url 'monitor:graph' my_model_pk %}">グラフ</a> </li> {% endif %} <li class="nav-item"> <a class="nav-link" href="{% url 'monitor:password_change' %}" class="logout">パスワード変更</a> </li> <li class="nav-item"> <a class="nav-link" href="{% url 'logout' %}">ログアウト</a> </li> {% else %} <li class="nav-item"> <a class="nav-link" href="{% url 'monitor:password_reset' %}">パスワード忘れ</a> </li> <li class="nav-item"> <a class="nav-link" href="{% url 'monitor:index' %}" class="login">ログイン</a> </li> {% endif %} </ul> </div> </div> </nav> {% block content %} {% endblock %} </main> </body>
urls.py
グラフ描画画面は詳細画面ごとに存在するものとします。
(”monitor/<int:pk>/graph/”)
base.htmlにおいて、「href=”{% url ‘monitor:graph’ my_model_pk %}」のようにpkをパラメータとしてページへのリンクを張っています。
# urls.py抜粋 urlpatterns = [ # トップ画面 path('', views.IndexView.as_view(), name='index'), # 詳細画面 path('monitor/<int:pk>/', views.DetailView.as_view(), name='detail'), # グラフ描画画面 path("monitor/<int:pk>/graph/", views.GraphView.as_view(), name='graph'), # パスワード変更画面 path('password_change/', views.PasswordChange.as_view(), name='password_change'), path('password_change/done/', views.PasswordChangeDone.as_view(), name='password_change_done'), # パスワードリセット画面 path('password_reset/', views.PasswordReset.as_view(), name='password_reset'), path('password_reset/done/', views.PasswordResetDone.as_view(), name='password_reset_done'), path('reset/<uidb64>/<token>/', views.PasswordResetConfirm.as_view(), name='password_reset_confirm'), path('reset/done/', views.PasswordChangeComplete.as_view(), name='password_reset_complete'), ]
動作確認
一覧画面
一覧画面では「グラフ」というメニューは表示されません。
詳細画面
詳細画面では「グラフ」というメニューが表示されます。
「グラフ」メニューにカーソルを持っていくと、各詳細画面のpk値に応じたリンクとなっていることがわかります。
以上で画面に応じたナビゲーションバーのメニュー切り替えサンプルは終わりです。
Django