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):」を定義することにより、テンプレートへデータを渡します。

https://docs.djangoproject.com/ja/2.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data

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

コメントを残す

メールアドレスが公開されることはありません。