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

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

認証は Web アプリ共通のニーズであるため、"Django Web プロジェクト" テンプレートには基本認証フローが含まれています (このチュートリアルの手順 6. で説明する "ポーリング Django Web プロジェクト" テンプレートにも、同じフローが含まれています)。いずれかの Django プロジェクト テンプレートを使用する場合、Visual Studio には Django プロジェクトの settings.py での認証に必要なすべてのモジュールが含まれています。

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

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

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

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

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

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

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

    Django Web プロジェクトのアプリ ページ上にある login コントロール

  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 を使用して、認証を確認できます。

    [Django Web プロジェクト] アプリ ページ上の Hello メッセージとログオフ コントロール

  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 = [
          # ...
          url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
          url(r'^admin/', include(admin.site.urls)),
      ]
      
    3. Django プロジェクトの settings.py ファイルで、INSTALLED_APPS コレクションに移動して 'django.contrib.admindocs' を追加します。

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

      Django 管理者インターフェイス

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

    url(r'^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 %}
    

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

    追加されたログオフ ページ

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

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

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

次の手順

注意

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

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

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

  • Web アプリを Azure App Service などの運用サーバーに展開します。 「Azure App Service に発行する」を参照してください。

  • 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 でホストできます) の運用レベルのデータ ストアにアプリを変更します。 「When to use SQLite」(SQLite を使用する場合) (sqlite.org) で説明されているように、SQLite は、1 日あたり 100,000 ヒット未満のトラフィックが中小規模のサイトには適していますが、高ボリュームのサイトにはお勧めできません。 また、単一のコンピューターに制限されているため、負荷分散処理や 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 ドキュメントを参照してください。

詳しい説明