手順 5: Django でユーザーを認証する

前の手順: 完全な Django Web プロジェクト テンプレートを使用する

認証は Web アプリ共通のニーズであるため、"Django Web プロジェクト" テンプレートには基本認証フローが含まれています。 いずれかの Django プロジェクト テンプレートを使用する場合、Visual Studio には Django プロジェクトの settings.py ファイルでの認証に必要なすべてのモジュールが含まれています。

この手順では、次のことを学習します。

  • Visual Studio テンプレートで提供される認証フローの使用方法 (手順 5-1)

手順 5-1: 認証フローを使用する

次の手順では、認証フローを利用して、プロジェクトの各部について説明します。

  1. プロジェクトのルートにある readme.html ファイルの指示に従ってスーパー ユーザー (管理者) アカウントをまだ作成していない場合は、すぐに作成します。

  2. [デバッグ]>[デバッグの開始] (F5 キー) を使用して、Visual Studio からアプリを実行します。 ブラウザーにアプリが表示されたら、ナビゲーション バーの右上に [ログイン] が表示されていることを確認します。

    Login control on the Django Web Project app page.

  3. templates/app/layout.html を開き、<div class="navbar ...> 要素にタグ {% include app/loginpartial.html %} が含まれていることを確認します。 {% include %} タグは、含まれているテンプレートにこの時点でインクルードされているファイルの内容を組み入れるように、Django のテンプレート システムに指示します。

  4. templates/app/loginpartial.html を開き、{% else %} タグと共に条件タグ {% if user.is_authenticated %} を使用して、ユーザーが認証済みかどうかに応じて異なる UI 要素を表示する方法を確認します。

    {% if user.is_authenticated %}
    <form id="logoutForm" action="/logout" method="post" class="navbar-right">
        {% csrf_token %}
        <ul class="nav navbar-nav navbar-right">
            <li><span class="navbar-brand">Hello {{ user.username }}!</span></li>
            <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
        </ul>
    </form>
    
    {% else %}
    
    <ul class="nav navbar-nav navbar-right">
        <li><a href="{% url 'login' %}">Log in</a></li>
    </ul>
    
    {% endif %}
    
  5. 最初にアプリを起動するときはどのユーザーも認証されていないので、このテンプレートのコードは、相対パス "login" への "ログイン" リンクのみを表示します。 (前のセクションで示したように) urls.py の指定に従って、そのルートは django.contrib.auth.views.login ビューにマップされ、次のデータを受け取ります。

    {
        'template_name': 'app/login.html',
        'authentication_form': app.forms.BootstrapAuthenticationForm,
        'extra_context':
        {
            'title': 'Log in',
            'year': datetime.now().year,
        }
    }
    

    ここで、template_name は、ログイン ページ用のテンプレート (この場合は templates/app/login.html) を特定します。 extra_context プロパティは、テンプレートに指定された既定のコンテキスト データに追加されます。 最後に、authentication_form は、テンプレートに form オブジェクトとして示される、ログインに使用するフォーム クラスを定義します。 既定値は AuthenticationForm (django.contrib.auth.views より) です。Visual Studio プロジェクト テンプレートでは代わりに、アプリの forms.py ファイルに定義された次のフォームを使用します。

    from django import forms
    from django.contrib.auth.forms import AuthenticationForm
    from django.utils.translation import ugettext_lazy as _
    
    class BootstrapAuthenticationForm(AuthenticationForm):
        """Authentication form which uses boostrap CSS."""
        username = forms.CharField(max_length=254,
                                   widget=forms.TextInput({
                                       'class': 'form-control',
                                       'placeholder': 'User name'}))
        password = forms.CharField(label=_("Password"),
                                   widget=forms.PasswordInput({
                                       'class': 'form-control',
                                       'placeholder':'Password'}))
    

    見てわかるように、このフォーム クラスは AuthenticationForm から派生し、明示的にユーザー名とパスワードのフィールドをオーバーライドして、プレースホルダー テキストを追加します。 Visual Studio テンプレートには、パスワード強度の検証を追加するなど、必要に応じてフォームをカスタマイズすることを予想して、この明示的なコードが含まれています。

  6. ログイン ページに移動すると、アプリは login.html テンプレートを表示します。 変数 {{ form.username }} および {{ form.password }} は、BootstrapAuthenticationForm から CharField フォームを表示します。 また、検証エラーを表示するための組み込みのセクションと、ソーシャル ログイン用にあらかじめ用意されている要素もあり、必要に応じてこれらのサービスを追加できます。

    {% extends "app/layout.html" %}
    
    {% block content %}
    
    <h2>{{ title }}</h2>
    <div class="row">
        <div class="col-md-8">
            <section id="loginForm">
                <form action="." method="post" class="form-horizontal">
                    {% csrf_token %}
                    <h4>Use a local account to log in.</h4>
                    <hr />
                    <div class="form-group">
                        <label for="id_username" class="col-md-2 control-label">User name</label>
                        <div class="col-md-10">
                            {{ form.username }}
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="id_password" class="col-md-2 control-label">Password</label>
                        <div class="col-md-10">
                            {{ form.password }}
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <input type="hidden" name="next" value="/" />
                            <input type="submit" value="Log in" class="btn btn-default" />
                        </div>
                    </div>
                    {% if form.errors %}
                    <p class="validation-summary-errors">Please enter a correct user name and password.</p>
                    {% endif %}
                </form>
            </section>
        </div>
        <div class="col-md-4">
            <section id="socialLoginForm"></section>
        </div>
    </div>
    
    {% endblock %}
    
  7. フォームを送信すると、Django は資格情報 (スーパー ユーザーの資格情報など) の認証を試みます。 認証に失敗した場合、現在のページに留まりますが、form.errors は true に設定されます。 認証に成功した場合、Django は "next" フィールド <input type="hidden" name="next" value="/" /> にある相対 URL に移動します。この例では、ホーム ページ (/) になっています。

  8. ここで、ホーム ページが再表示されると、loginpartial.html テンプレートが表示されるときに、user.is_authenticated プロパティが true になります。 その結果、Hello (<ユーザー名>) メッセージと [Log off] が表示されます。 アプリの他の部分で user.is_authenticated を使用して、認証を確認できます。

    Hello message and logoff control on the Django Web Project app page.

  9. 認証済みユーザーに特定のリソースに対するアクセス権が付与されたかどうかを確認するには、ユーザー固有のアクセス許可をデータベースから取得する必要があります。 詳細については、Django 認証システムの使用に関するページ (Django docs) を参照してください。

  10. 特に、ス―パー ユーザーまたは管理者は、相対 URL "/admin/" および "/admin/doc/" を使用して、組み込みの Django 管理者インターフェイスにアクセスします。これらのインターフェイスを有効にするには、次の手順のようにします。

    1. 環境に docutils Python パッケージをインストールします。 インストールするには、requirements.txt ファイルに "docutils" を追加することをお勧めします。 次に、ソリューション エクスプローラーでプロジェクトを展開し、[Python 環境] ノードを展開し、使っている環境を右クリックし、[requirements.txt からのインストール] を選びます。

    2. Django プロジェクトの urls.py ファイルを開き、次を追加します。

      from django.conf.urls import include
      from django.contrib import admin
      admin.autodiscover()
      
      urlpatterns = [
          path('admin/doc/', include('django.contrib.admindocs.urls'))
      ]
      
    3. Django プロジェクトの settings.py ファイルで、INSTALLED_APPS コレクションに移動して 'django.contrib.admindocs' を追加します。

    4. アプリを再起動したときに、"/admin/" および "/admin/doc/" に移動して、追加のユーザー アカウント作成などのタスクを実行できます。

      Django administrator interface.

  11. 認証フローの最後の部分は、ログオフです。 loginpartial.html でわかるように、[Log off] リンクは単純に相対 URL "/login" に対する POST を実行します。これは、組み込みのビュー django.contrib.auth.views.logout によって処理されます。 このビューには UI が表示されず、ホーム ページへの移動のみを行います (urls.py の "^logout$" パターンで確認できます)。 ログオフ ページを表示する場合は、最初に、次のように URL パターンを変更して、"template_name" プロパティを追加し "next_page" プロパティを削除します。

    path('logout/',
        django.contrib.auth.views.logout,
        {
            'template_name': 'app/loggedoff.html',
            # 'next_page': '/',
        },
        name='logout')
    

    次に、以下の (最小限の) 内容で templates/app/loggedoff.html を作成します。

    {% extends "app/layout.html" %}
    {% block content %}
    <h3>You have been logged off</h3>
    {% endblock %}
    

    結果として、次のように表示されます。

    Added logged off page.

  12. すべて完了したら、サーバーを停止し、もう一度ソース管理に変更をコミットします。

質問: <form> 要素に表示される {% csrf_token %} タグの目的は何ですか。

回答: {% csrf_token %} タグには Django の組み込みのクロスサイト リクエスト フォージェリ (csrf) 保護 (Django docs) が含まれています。 通常、このタグは、フォームなどの POST、PUT、または DELETE 要求のメソッドに関連する任意の要素に追加します。 その後、テンプレートのレンダリング関数 (render) により、必要な保護が挿入されます。

次のステップ

Note

このチュートリアルの途中で Visual Studio ソリューションをソース コード管理にコミットした場合は、もう 1 つのコミットを実行することをお勧めします。 ソリューションは、GitHub Microsoft/python-sample-vs-learning-django のチュートリアル ソース コードと一致するようにします。

Visual Studio で "空の Django Web プロジェクト" と "Django Web プロジェクト" の各テンプレートを全体的に確認しました。 ビューやテンプレートの使い方など、Django のすべての基本を学習しました。 また、ルーティング、認証、使用されるデータベース モデルについても確認しました。 これで、必要なビューとモデルがある独自の Web アプリを作成できるようになったはずです。

開発用コンピューター上で Web アプリを実行することは、アプリを顧客に提供するための単なる 1 つの手順です。 次の手順には以下のタスクが含まれる場合があります。

  • templates/404.html というテンプレートを作成して、404 ページをカスタマイズします。 このテンプレートがある場合、Django は既定のテンプレートではなくこのテンプレートを使用します。 詳細については、Django ドキュメントの「Error views」(エラー ビュー) を参照してください。

  • tests.py で単体テストを作成します。Visual Studio プロジェクト テンプレートには、そのための出発点が用意されています。詳細については、Django ドキュメントの「Writing your first Django app, part 5 - testing」(最初の Django アプリを作成する、パート 5 - テスト) と「Testing in Django」(Django のテスト) を参照してください。

  • SQLite から、PostgreSQL、MySQL、SQL Server など (これらはいずれも Azure でホストできます) の運用レベルのデータ ストアにアプリを変更します。 SQLite を使用するタイミングに関するページ (sqlite.org) で説明されているように、1 日あたりのヒット数が 100 K 未満で、トラフィックが低から中程度のサイトでは SQLite は問題なく機能します。 しかし、規模がさらに大きい場合は SQLite をお勧めしません。 また、SQLite は単一のコンピューターに制限されているため、負荷分散処理や geo レプリケーションなど、マルチサーバーのシナリオには使用できません。 他のデータベースに対する Django のサポートについては、「Database setup」(データベースの設定) を参照してください。 テーブルや BLOB のような Azure ストレージ サービスを使用する場合は、Azure SDK for Python も使用できます。

  • Azure DevOps などのサービスに対して、継続的インテグレーション/継続的配置パイプラインを設定します。 (Azure Repos、GitHub などの場所を使った) ソース管理を利用するだけでなく、リリースの前提条件として単体テストを自動的に実行するように Azure DevOps プロジェクトを構成することもできます。 また、運用環境にデプロイする前に、さらにテストを行うためにステージング サーバーにデプロイするようにパイプラインを構成することもできます。 さらに、Azure DevOps は App Insights などの監視ソリューションと統合されているので、アジャイル計画ツールを使用してサイクル全体に対応することができます。 詳細については、「Azure DevOps プロジェクトで Python 用の CI/CD パイプラインを作成する」、および一般的な Azure DevOps ドキュメントを参照してください。

詳しい説明