に参加して、VS Code の AI 支援開発について学びましょう。

Visual Studio Code での Django チュートリアル

Django は、迅速で安全、かつスケーラブルな Web 開発のために設計された高レベルの Python フレームワークです。Django には、URL ルーティング、ページテンプレート、およびデータ操作のための豊富なサポートが含まれています。

この Django チュートリアルでは、共通のベーステンプレートを使用する 3 つのページを持つシンプルな Django アプリを作成します。VS Code ターミナル、エディター、デバッガーで Django を操作する方法を理解するために、Visual Studio Code のコンテキストでこのアプリを作成します。このチュートリアルでは、データモデルの操作や管理インターフェースの作成など、Django 自体のさまざまな詳細については説明しません。これらの側面に関するガイダンスについては、このチュートリアルの最後にある Django ドキュメントのリンクを参照してください。

この Django チュートリアルで完成したコードプロジェクトは GitHub で見つけることができます: python-sample-vscode-django-tutorial

問題が発生した場合は、Python 拡張機能 Discussions Q&A で回答を検索したり、質問したりできます。

前提条件

この Django チュートリアルを正常に完了するには、次のことを行う必要があります (これは、一般的な Python チュートリアル と同じ手順です)

  1. Python 拡張機能 をインストールします。

  2. Python 3 のバージョン (このチュートリアルが書かれているバージョン) をインストールします。オプションは次のとおりです

    • (すべてのオペレーティングシステム) python.org からダウンロードします。通常は、ページに最初に表示される Download Python 3.9.1 ボタン (または最新バージョン) を使用します。
    • (Linux) 組み込みの Python 3 インストールで問題なく動作しますが、他の Python パッケージをインストールするには、ターミナルで sudo apt install python3-pip を実行する必要があります。
    • (macOS) brew install python3 を使用して macOS の Homebrew 経由でインストールします (macOS のシステムインストール Python はサポートされていません)。
    • (すべてのオペレーティング システム) Anaconda からダウンロードします (データ サイエンス目的)。
  3. Windows では、Python インタープリターの場所が PATH 環境変数に含まれていることを確認してください。コマンド プロンプトで path を実行して場所を確認できます。Python インタープリターのフォルダーが含まれていない場合は、Windows 設定を開き、「環境」を検索し、アカウントの環境変数を編集 を選択し、Path 変数を編集してそのフォルダーを含めます。

Django チュートリアルのプロジェクト環境を作成する

このセクションでは、Django がインストールされる仮想環境を作成します。仮想環境を使用することで、Django がグローバルな Python 環境にインストールされるのを防ぎ、アプリケーションで使用されるライブラリを正確に制御できます。仮想環境を使用すると、環境の requirements.txt ファイルを作成 するのも簡単になります。

  1. ファイルシステムに、hello_django のような、このチュートリアル用のプロジェクトフォルダーを作成します。

  2. そのフォルダー内で、現在のインタープリターに基づいて .venv という名前の仮想環境を作成するために、次のコマンド (コンピューターに適したコマンド) を使用します。

    # Linux
    sudo apt-get install python3-venv    # If needed
    python3 -m venv .venv
    source .venv/bin/activate
    
    # macOS
    python3 -m venv .venv
    source .venv/bin/activate
    
    # Windows
    py -3 -m venv .venv
    .venv\scripts\activate
    

    : 上記のコマンドを実行するときは、標準の Python インストールを使用してください。Anaconda インストールからの python.exe を使用すると、ensurepip モジュールが利用できないためにエラーが表示され、環境が未完成の状態になります。

  3. code . を実行するか、VS Code を実行して ファイル > フォルダーを開く コマンドを使用して、プロジェクトフォルダーを VS Code で開きます。

  4. VS Code で、コマンドパレットを開きます (表示 > コマンドパレット または (⇧⌘P (Windows、Linux Ctrl+Shift+P)))。次に、Python: インタープリターを選択 コマンドを選択します

    Django tutorial: opening the Command Palette in VS Code

  5. このコマンドは、VS Code が自動的に見つけられる利用可能なインタープリターのリストを表示します (あなたのリストは異なります。目的のインタープリターが表示されない場合は、Python 環境の構成 を参照してください)。リストから、プロジェクトフォルダー内の ./.venv または .\.venv で始まる仮想環境を選択します

    Django tutorial: Selecting the virtual environment for Python

  6. コマンドパレットから ターミナル: 新しいターミナルを作成 (⌃⇧` (Windows、Linux Ctrl+Shift+`)) を実行します。これにより、ターミナルが作成され、アクティベーションスクリプトを実行することで仮想環境が自動的にアクティブ化されます。

    : Windows で、デフォルトのターミナル タイプが PowerShell の場合、システムでスクリプトの実行が無効になっているため activate.ps1 を実行できないというエラーが表示されることがあります。このエラーには、スクリプトを許可する方法に関する情報へのリンクが含まれています。それ以外の場合は、ターミナル: デフォルト プロファイルを選択 を使用して、「コマンド プロンプト」または「Git Bash」を代わりにデフォルトとして設定してください。

  7. 選択した環境は、VS Code ステータスバーの右側に表示され、仮想環境を使用していることを示す ('.venv': venv) インジケーターが表示されます。

    Django tutorial: selected environment showing in the VS Code status bar

  8. VS Code ターミナルで次のコマンドを実行して、仮想環境の pip を更新します

    python -m pip install --upgrade pip
    
  9. VS Code ターミナルで次のコマンドを実行して、仮想環境に Django をインストールします

    python -m pip install django
    

これで、Django コードを記述するための自己完結型環境が準備できました。VS Code は、ターミナル: 新しいターミナルを作成 (⌃⇧` (Windows、Linux Ctrl+Shift+`)) を使用すると、環境を自動的にアクティブ化します。別のコマンドプロンプトまたはターミナルを開く場合は、source .venv/bin/activate (Linux/macOS) または .venv\Scripts\Activate.ps1 (Windows) を実行して環境をアクティブ化します。コマンドプロンプトの先頭に (.venv) と表示されていれば、環境がアクティブ化されています。

最小限の Django アプリを作成して実行する

Django の用語では、「Django プロジェクト」はいくつかのサイトレベルの構成ファイルと、完全な Web アプリケーションを作成するために Web ホストにデプロイする 1 つ以上の「アプリ」で構成されます。Django プロジェクトには複数のアプリを含めることができ、各アプリは通常、プロジェクト内で独立した機能を持っています。また、同じアプリを複数の Django プロジェクトに含めることもできます。アプリ自体は、Django が期待する特定の規則に従う単なる Python パッケージです。

したがって、最小限の Django アプリを作成するには、まずアプリのコンテナとして機能する Django プロジェクトを作成し、次にアプリ自体を作成する必要があります。どちらの目的にも、Django パッケージをインストールするとインストールされる Django 管理ユーティリティ django-admin を使用します。

Django プロジェクトを作成する

  1. 仮想環境がアクティブ化されている VS Code ターミナルで、次のコマンドを実行します

    django-admin startproject web_project .
    

    この startproject コマンドは、(末尾の . の使用により) 現在のフォルダーがプロジェクトフォルダーであることを想定しており、その中に次を作成します。

    • manage.py: プロジェクトの Django コマンドライン管理ユーティリティです。python manage.py [options] を使用して、プロジェクトの管理コマンドを実行します。

    • web_project というサブフォルダーには、次のファイルが含まれています

      • __init__.py: このフォルダーが Python パッケージであることを Python に伝える空のファイル。
      • asgi.py: ASGI互換 Web サーバーがプロジェクトをサービスするためのエントリポイント。これは通常、本番 Web サーバーのフックを提供するため、そのままにしておきます。
      • settings.py: Django プロジェクトの設定が含まれており、Web アプリ開発中に変更します。
      • urls.py: Django プロジェクトの目次が含まれており、開発中にこれも変更します。
      • wsgi.py: WSGI互換 Web サーバーがプロジェクトをサービスするためのエントリポイント。これは通常、本番 Web サーバーのフックを提供するため、そのままにしておきます。
  2. 次のコマンドを実行して、空の開発用データベースを作成します

    python manage.py migrate
    

    サーバーを初めて実行すると、開発目的のデフォルトの SQLite データベースが db.sqlite3 ファイルに作成されますが、低容量の Web アプリケーションでは本番環境でも使用できます。データベースに関する追加情報については、「データベースの種類」セクションを参照してください。

  3. Django プロジェクトを確認するには、仮想環境がアクティブになっていることを確認し、python manage.py runserver コマンドを使用して Django の開発サーバーを起動します。サーバーはデフォルトのポート 8000 で実行され、ターミナルウィンドウに次のような出力が表示されます

    Watching for file changes with StatReloader
    Performing system checks...
    
    System check identified no issues (0 silenced).
    June 13, 2023 - 18:38:07
    Django version 4.2.2, using settings 'web_project.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.
    

    Django の組み込み Web サーバーは、ローカル開発目的でのみ使用されます。ただし、Web ホストにデプロイする場合、Django は代わりにホストの Web サーバーを使用します。Django プロジェクトの wsgi.py および asgi.py モジュールは、本番サーバーへのフックを処理します。

    デフォルトの 8000 以外のポートを使用したい場合は、python manage.py runserver 5000 のように、コマンドラインでポート番号を指定します。

  4. ターミナル出力ウィンドウの http://127.0.0.1:8000/ URL を Ctrl+クリック すると、デフォルトのブラウザでそのアドレスが開きます。Django が正しくインストールされ、プロジェクトが有効であれば、下に示されているデフォルトページが表示されます。VS Code のターミナル出力ウィンドウにもサーバーログが表示されます。

    Django tutorial: default view of empty Django project

  5. 完了したら、ブラウザウィンドウを閉じ、ターミナル出力ウィンドウに表示されている Ctrl+C を使用して VS Code でサーバーを停止します。

Django アプリケーションを作成する

  1. 仮想環境がアクティブ化された VS Code ターミナルで、プロジェクトフォルダー (manage.py が存在する場所) で管理ユーティリティの startapp コマンドを実行します

    python manage.py startapp hello
    

    このコマンドは、多数のコードファイルと1つのサブフォルダーを含む hello というフォルダーを作成します。これらの中で、頻繁に操作するのは views.py (Web アプリのページを定義する関数が含まれています) と models.py (データオブジェクトを定義するクラスが含まれています) です。migrations フォルダーは、このチュートリアルの後半で説明するように、Django の管理ユーティリティがデータベースバージョンを管理するために使用します。他にも、apps.py (アプリ構成)、admin.py (管理インターフェース を作成するため)、tests.py (テストを作成するため) がありますが、ここでは扱いません。

  2. アプリのホームページの単一のビューを作成する次のコードと一致するように hello/views.py を変更します

    from django.http import HttpResponse
    
    def home(request):
        return HttpResponse("Hello, Django!")
    
  3. 以下の内容で hello/urls.py ファイルを作成します。urls.py ファイルは、さまざまな URL を適切なビューにルーティングするためのパターンを指定する場所です。以下のコードには、アプリのルート URL ("") を、hello/views.py に追加したばかりの views.home 関数にマッピングする 1 つのルートが含まれています。

    from django.urls import path
    from hello import views
    
    urlpatterns = [
        path("", views.home, name="home"),
    ]
    
  4. web_project フォルダーにも urls.py ファイルが含まれており、ここで URL ルーティングが実際に処理されます。web_project/urls.py を開いて、次のコードと一致するように変更します (必要に応じて、指示コメントは保持できます)。このコードは、django.urls.include を使用してアプリの hello/urls.py を取り込み、アプリのルートをアプリ内に保持します。この分離は、プロジェクトに複数のアプリが含まれている場合に役立ちます。

    from django.contrib import admin
    from django.urls import include, path
    
    urlpatterns = [
        path("", include("hello.urls")),
        path('admin/', admin.site.urls)
    ]
    
  5. 変更したファイルをすべて保存します。

  6. VS Code ターミナルで、仮想環境を再度アクティブにして、python manage.py runserver で開発サーバーを実行し、ブラウザーで http://127.0.0.1:8000/ を開いて「Hello, Django」と表示されるページを確認します。

    Django tutorial: the basic Django app running in a browser

デバッガー起動プロファイルを作成する

毎回 python manage.py runserver と入力しなくても、サーバーを実行してアプリをテストするもっと簡単な方法はないかと、おそらくすでに疑問に思っていることでしょう。幸いなことに、あります!VS Code でカスタマイズされた起動プロファイルを作成できます。これは、避けられないデバッグの練習にも使用されます。

  1. VS Code の 実行 ビューに切り替えます (左側のアクティビティバーまたは F5 を使用)。「実行とデバッグをカスタマイズするには、launch.json ファイルを作成してください」というメッセージが表示される場合があります。これは、デバッグ構成を含む launch.json ファイルがまだないことを意味します。launch.json ファイルを作成する リンクをクリックすると、VS Code がそれを作成できます。

    Django tutorial: initial view of the debug panel

  2. リンクを選択すると、VS Code はデバッグ構成を要求します。ドロップダウンから Django を選択すると、VS Code は Django 実行構成で新しい launch.json ファイルを生成します。launch.json ファイルには多数のデバッグ構成が含まれており、それぞれが configuration 配列内の個別の JSON オブジェクトです。

  3. スクロールダウンして、「Python: Django」という名前の構成を調べます

    {
      // Use IntelliSense to learn about possible attributes.
      // Hover to view descriptions of existing attributes.
      // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Python Debugger: Django",
          "type": "debugpy",
          "request": "launch",
          "program": "${workspaceFolder}\\manage.py",
          "args": ["runserver"],
          "django": true,
          "justMyCode": true
        }
      ]
    }
    

    この構成は、選択した Python インタープリターと args リストの引数を使用して "${workspaceFolder}/manage.py" を実行するように VS Code に指示します。この構成で VS Code デバッガーを起動することは、アクティブな仮想環境で VS Code ターミナルで python manage.py runserver を実行することと同じです。(必要に応じて、"5000" のようなポート番号を args に追加できます。) "django": true エントリは、Django ページテンプレートのデバッグを有効にするように VS Code に指示します。これについては、このチュートリアルの後半で説明します。

  4. 実行 > デバッグの開始 メニューコマンドを選択するか、リストの横にある緑色の デバッグの開始 矢印 (F5) を選択して、構成をテストします。

    Django tutorial: start debugging/continue arrow on the debug toolbar

  5. ターミナル出力ウィンドウの http://127.0.0.1:8000/ URL を Ctrl+クリック してブラウザを開き、アプリが正常に実行されていることを確認します。

  6. 終了したら、ブラウザを閉じ、デバッガーを停止します。デバッガーを停止するには、ツールバーの停止ボタン (赤い四角) または 実行 > デバッグの停止 コマンド (⇧F5 (Windows, Linux Shift+F5)) を使用します。

  7. いつでも 実行 > デバッグの開始 を使用してアプリをテストできるようになりました。これにより、変更されたすべてのファイルが自動的に保存されるという利点もあります。

デバッガーを探索する

デバッグにより、実行中のプログラムを特定のコード行で一時停止する機会が得られます。プログラムが一時停止している間は、変数を調べたり、デバッグ コンソール パネルでコードを実行したり、デバッグ で説明されている機能を利用したりできます。デバッガーを実行すると、デバッグ セッションが開始される前に、変更されたファイルが自動的に保存されます。

開始する前に: 前のセクションの最後に、ターミナルで Ctrl+C を使用して実行中のアプリを停止したことを確認してください。1 つのターミナルでアプリを実行したままにすると、ポートが占有されたままになります。その結果、同じポートを使用してデバッガーでアプリを実行すると、元の実行中のアプリがすべてのリクエストを処理し、デバッグ中のアプリでアクティビティが表示されず、プログラムがブレークポイントで停止しません。つまり、デバッガーが機能していないように見える場合は、他のアプリのインスタンスがまだ実行されていないことを確認してください。

  1. hello/urls.py で、urlpatterns リストにルートを追加します

    path("hello/<name>", views.hello_there, name="hello_there"),
    

    path の最初の引数は、*name* と呼ばれる変数文字列を受け入れるルート「hello/」を定義します。文字列は、path の 2 番目の引数で指定された views.hello_there 関数に渡されます。

    URL ルートは大文字と小文字を区別します。たとえば、ルート /hello//Hello/ とは異なります。同じビュー関数で両方を処理する場合は、各バリアントのパスを定義します。

  2. デバッガーでステップ実行できる hello_there 関数を定義するために、views.py の内容を次のコードに置き換えます。

    import re
    from django.utils.timezone import datetime
    from django.http import HttpResponse
    
    def home(request):
        return HttpResponse("Hello, Django!")
    
    def hello_there(request, name):
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        # Filter the name argument to letters only using regular expressions. URL arguments
        # can contain arbitrary text, so we restrict to safe characters only.
        match_object = re.match("[a-zA-Z]+", name)
    
        if match_object:
            clean_name = match_object.group(0)
        else:
            clean_name = "Friend"
    
        content = "Hello there, " + clean_name + "! It's " + formatted_now
        return HttpResponse(content)
    

    URL ルートで定義された name 変数は、hello_there 関数への引数として与えられます。コードコメントで説明されているように、アプリへのさまざまな攻撃を回避するために、ユーザーが提供する任意の情報を常にフィルタリングしてください。この場合、コードは名前引数を文字のみを含むようにフィルタリングし、制御文字、HTML などの挿入を回避します。(次のセクションでテンプレートを使用する場合、Django は自動フィルタリングを実行するため、このコードは不要です。)

  3. hello_there 関数の最初のコード行 (now = datetime.now()) にブレークポイントを設定するには、次のいずれかの操作を行います

    • その行にカーソルを置いて F9 を押すか、
    • その行にカーソルを置いて 実行 > ブレークポイントの切り替え メニュー コマンドを選択するか、
    • 行番号の左側の余白を直接クリックします (ホバーすると薄い赤い点が表示されます)。

    ブレークポイントは左余白に赤い点として表示されます

    Django tutorial: a breakpoint set on the first line of the hello_there function

  4. 実行 > デバッグの開始 メニュー コマンドを選択するか、リストの横にある緑色の デバッグの開始 矢印 (F5) を選択してデバッガーを開始します

    Django tutorial: start debugging/continue arrow on the debug toolbar

    ステータス バーの色がデバッグを示すように変化することを確認します

    Django tutorial: appearance of the debugging status bar

    VS Code には、デバッグツールバー (下図) も表示され、以下の順序でコマンドが含まれています: 一時停止 (または続行、F5)、ステップオーバー (F10)、ステップイン (F11)、ステップアウト (⇧F11 (Windows, Linux Shift+F11))、再起動 (⇧⌘F5 (Windows, Linux Ctrl+Shift+F5))、停止 (⇧F5 (Windows, Linux Shift+F5))。各コマンドの説明については、VS Code のデバッグ を参照してください。

    Django tutorial: the VS Code debug toolbar

  5. 出力は「Python デバッグコンソール」ターミナルに表示されます。ブラウザを開き、http://127.0.0.1:8000/hello/VSCode に移動します。ページがレンダリングされる前に、VS Code は設定したブレークポイントでプログラムを一時停止します。ブレークポイントの小さな黄色の矢印は、それが次に実行されるコード行であることを示しています。

    Django tutorial: VS Code paused at a breakpoint

  6. ステップオーバーを使用して、now = datetime.now() ステートメントを実行します。

  7. VS Code ウィンドウの左側には、now などのローカル変数や、name などの引数を示す 変数 ペインが表示されます。その下には、ウォッチコール スタックブレークポイント のペインがあります (詳細については、VS Code デバッグ を参照してください)。ローカル セクションで、さまざまな値を展開してみてください。値をダブルクリック (または Enter (Windows, Linux F2) を使用) して変更することもできます。ただし、now のような変数を変更すると、プログラムが破損する可能性があります。開発者は通常、コードが最初から正しい値を生成しなかった場合にのみ、値を修正するために変更を加えます。

    Django tutorial: local variables and arguments in VS Code during debugging

  8. プログラムが一時停止しているとき、デバッグコンソール パネル (ターミナルパネルの「Python デバッグコンソール」とは異なります) を使用すると、式を試したり、プログラムの現在の状態を使用してコードの一部を試したりできます。たとえば、now = datetime.now() の行をステップ実行した後、異なる日付/時刻形式を試すことができます。エディターで now.strftime("%A, %d %B, %Y at %X") と読み取れるコードを選択し、右クリックして デバッグ: 評価 を選択して、そのコードをデバッグコンソールに送信し、そこで実行します。

    now.strftime("%A, %d %B, %Y at %X")
    'Friday, 07 September, 2018 at 07:46:32'
    

    ヒント: デバッグ コンソール には、ターミナルに表示されない可能性のあるアプリ内の例外も表示されます。たとえば、実行とデバッグ ビューの コール スタック 領域に「例外で一時停止」メッセージが表示された場合は、デバッグ コンソール に切り替えて例外メッセージを確認してください。

  9. その行をデバッグ コンソール下部の > プロンプトにコピーし、書式設定を変更してみてください

    now.strftime("%A, %d %B, %Y at %X")
    'Tuesday, 13 June, 2023 at 18:03:19'
    now.strftime("%a, %d %b, %Y at %X")
    'Tue, 13 Jun, 2023 at 18:03:19'
    now.strftime("%a, %d %b, %y at %X")
    'Tue, 13 Jun, 23 at 18:03:19'
    
  10. 必要に応じて、さらに数行のコードをステップ実行してから、続行 (F5) を選択してプログラムを実行させます。ブラウザ ウィンドウに結果が表示されます

    Django tutorial: result of the modified program

  11. コード内の行を別の datetime 形式 (例: now.strftime("%a, %d %b, %y at %X")) を使用するように変更し、ファイルを保存します。Django サーバーは自動的にリロードされるため、デバッガーを再起動する必要なく変更が適用されます。ブラウザでページを更新して更新を確認します。

  12. 終了したら、ブラウザを閉じ、デバッガーを停止します。デバッガーを停止するには、ツールバーの停止ボタン (赤い四角) または 実行 > デバッグの停止 コマンド (⇧F5 (Windows, Linux Shift+F5)) を使用します。

ヒント: http://127.0.0.1:8000/hello/VSCode のような特定の URL に繰り返し移動しやすくするには、その URL を views.py のようなファイルのどこかに print ステートメントを使用して出力します。URL は VS Code ターミナルに表示され、Ctrl+クリック を使用してブラウザで開くことができます。

定義へ移動および定義をピーク コマンド

Django またはその他のライブラリを操作している間、それらのライブラリ自体のコードを調べたい場合があります。VS Code は、クラスやその他のオブジェクトの定義に直接移動する 2 つの便利なコマンドを提供します。

  • 定義へ移動 は、コードからオブジェクトを定義するコードにジャンプします。たとえば、views.pyhome 関数で HttpResponse を右クリックし、定義へ移動 (または F12 を使用) を選択すると、Django ライブラリのクラス定義に移動します。

  • 定義をピーク (⌥F12 (Windows Alt+F12, Linux Ctrl+Shift+F10)、右クリック コンテキスト メニューにもあります) も同様ですが、クラス定義をエディターに直接表示します (コードを隠さないようにエディター ウィンドウにスペースを作成します)。Escape を押してピーク ウィンドウを閉じるか、右上隅の x を使用します。

    Django tutorial: Peek Definition showing the Flask class inline

テンプレートを使用してページをレンダリングする

このチュートリアルでこれまで作成したアプリは、Python コードからプレーンテキストの Web ページのみを生成します。コードで HTML を直接生成することは可能ですが、開発者は、アプリが クロスサイトスクリプティング (XSS) 攻撃 にさらされるため、そのような慣行を避けます。たとえば、このチュートリアルの hello_there 関数では、content = "

Hello there, " + clean_name + "!

" のようにコードで出力をフォーマットすることを考えるかもしれませんが、その結果の content がブラウザーに直接渡されます。この開口部により、攻撃者は、JavaScript コードを含む悪意のある HTML を URL に配置でき、それが clean_name に入り込み、最終的にブラウザーで実行されることになります。

はるかに良い方法は、テンプレート を使用して HTML をコードから完全に分離することです。これにより、コードはデータ値のみに関心を持ち、レンダリングには関心を持ちません。

Django では、テンプレートは、コードが実行時に提供する値のプレースホルダーを含む HTML ファイルです。Django テンプレートエンジンは、ページのレンダリング時に置換を処理し、XSS 攻撃を防ぐための自動エスケープを提供します (つまり、データ値で HTML を使用しようとすると、HTML はプレーンテキストとしてのみレンダリングされます)。したがって、コードはデータ値のみに関心を持ち、テンプレートはマークアップのみに関心を持ちます。Django テンプレートは、テンプレート継承などの柔軟なオプションを提供します。これにより、共通のマークアップを持つベースページを定義し、そのベースにページ固有の追加で構築できます。

このセクションでは、テンプレートを使用して単一のページを作成することから始めます。その後のセクションでは、静的ファイルを配信するようにアプリを設定し、ベーステンプレートからナビゲーションバーを含む複数のページをアプリに追加します。Django テンプレートは、制御フローと反復もサポートしています。これについては、このチュートリアルの後半でテンプレートデバッグのコンテキストで説明します。

  1. web_project/settings.py ファイルで、INSTALLED_APPS リストを見つけて、次のエントリを追加します。これにより、プロジェクトがアプリのテンプレート処理を認識できるようになります。

    'hello',
    
  2. hello フォルダー内に templates という名前のフォルダーを作成し、次にアプリ名と一致する別のサブフォルダー hello を作成します (この2層のフォルダー構造は典型的な Django の慣例です)。

  3. templates/hello フォルダーに、以下の内容で hello_there.html というファイルを作成します。このテンプレートには、「name」と「date」という名前のデータ値のプレースホルダーが2つ含まれており、中括弧 {{}} で区切られています。その他の不変のテキストはすべてテンプレートの一部であり、書式設定マークアップ ( など) も含まれています。ご覧のとおり、テンプレートのプレースホルダーには書式設定も含まれる場合があります。パイプ | 記号の後の式は、この場合、Django の組み込みの 日付フィルター時間フィルター を使用しています。したがって、コードは、事前フォーマットされた文字列ではなく、datetime *値* を渡すだけで済みます。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>Hello, Django</title>
        </head>
        <body>
            <strong>Hello there, {{ name }}!</strong> It's {{ date | date:"l, d F, Y" }} at {{ date | time:"H:i:s" }}
        </body>
    </html>
    
  4. views.py の冒頭に、次の import ステートメントを追加します

    from django.shortcuts import render
    
  5. また、views.py で、hello_there 関数を django.shortcuts.render メソッドを使用してテンプレートをロードし、テンプレートコンテキスト を提供するように変更します。コンテキストは、テンプレート内で使用するための変数のセットです。render 関数は、要求オブジェクト、次に templates フォルダーに対する相対パス、次にコンテキストオブジェクトを受け取ります。(開発者は通常、テンプレートにそれらを使用する関数と同じ名前を付けますが、コード内で常に正確なファイル名を参照するため、名前を一致させる必要はありません。)

    def hello_there(request, name):
        print(request.build_absolute_uri()) #optional
        return render(
            request,
            'hello/hello_there.html',
            {
                'name': name,
                'date': datetime.now()
            }
        )
    

    これでコードがはるかにシンプルになり、マークアップと書式設定はすべてテンプレートに含まれるため、データ値のみに関心があることがわかります。

  6. プログラムを開始し (デバッガー内または外部で ⌃F5 (Windows, Linux Ctrl+F5) を使用)、/hello/name URL に移動して結果を確認します。

  7. また、 のような名前を使用して /hello/name URL に移動して、Django の自動エスケープの動作を確認してください。「name」の値は、実際の要素としてレンダリングされるのではなく、ブラウザでプレーンテキストとして表示されます。

静的ファイルを配信する

静的ファイルとは、CSS ファイルなど、Web アプリケーションが特定の要求に対してそのまま返すコンテンツのことです。静的ファイルを配信するには、settings.pyINSTALLED_APPS リストに django.contrib.staticfiles が含まれている必要があります。これはデフォルトで含まれています。

Django で静的ファイルを配信するのは、特に本番環境にデプロイする場合、一種の技術です。ここで示すのは、Django 開発サーバーと Gunicorn のような本番サーバーの両方で機能するシンプルなアプローチです。ただし、静的ファイルの完全な扱いはこのチュートリアルの範囲外であるため、詳細については、Django ドキュメントの 静的ファイルの管理 を参照してください。

本番環境に切り替える際は、settings.py に移動し、DEBUG=False を設定し、ALLOWED_HOSTS = ['*'] を特定のホストを許可するように変更します。これにより、コンテナを使用する場合に追加の作業が必要になる場合があります。詳細については、Issue 13 を参照してください。

静的ファイル用のアプリを準備する

  1. プロジェクトの web_project/urls.py に、次の import ステートメントを追加します。

    from django.contrib.staticfiles.urls import staticfiles_urlpatterns
    
  2. 同じファイルで、最後に次の行を追加します。これにより、標準の静的ファイル URL がプロジェクトが認識するリストに含まれます。

    urlpatterns += staticfiles_urlpatterns()
    

テンプレート内の静的ファイルを参照する

  1. hello フォルダーに static という名前のフォルダーを作成します。

  2. static フォルダー内に、アプリ名と一致する hello というサブフォルダーを作成します。

    この追加のサブフォルダーの理由は、Django プロジェクトを本番サーバーにデプロイするときに、すべての静的ファイルを単一のフォルダーに収集し、それを専用の静的ファイルサーバーで提供するためです。static/hello サブフォルダーにより、アプリの静的ファイルが収集されたときに、アプリ固有のサブフォルダーに配置され、同じプロジェクト内の他のアプリからのファイルと衝突しないようになります。

  3. static/hello フォルダーに、次の内容で site.css というファイルを作成します。このコードを入力した後、VS Code が CSS ファイルに提供する構文強調表示、および色プレビューも確認してください。

    .message {
        font-weight: 600;
        color: blue;
    }
    
  4. templates/hello/hello_there.html</code> 要素の後に次の行を追加します。<code>{% load static %}</code> タグはカスタムの Django テンプレートタグセットであり、<code>{% static %}</code> を使用してスタイルシートのようなファイルを参照できます。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% load static %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">link</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> rel</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"stylesheet"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> type</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"text/css"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% static 'hello/site.css' %}"</span><span style="--shiki-dark:#808080;--shiki-light:#800000"> /></span></span> <span class="line"></span></code></pre> </li> <li> <p>また、<code>templates/hello/hello_there.html</code> の <code><body></code> 要素の内容を、<code><strong></code> タグの代わりに <code>message</code> スタイルを使用する次のマークアップに置き換えます。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">span</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"message"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Hello, there {{ name }}!</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">span</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> It's {{ date | date:'l, d F, Y' }} at {{ date | time:'H:i:s' }}.</span></span> <span class="line"></span></code></pre> </li> <li> <p>アプリを実行し、/hello/name URL に移動して、メッセージが青色でレンダリングされることを確認します。完了したらアプリを停止します。</p> </li> </ol> <h3 id="_use-the-collectstatic-command" data-needslink="_use-the-collectstatic-command">collectstatic コマンドを使用する</h3> <p>本番環境へのデプロイでは、通常、<code>python manage.py collectstatic</code> コマンドを使用して、アプリのすべての静的ファイルを単一のフォルダーに収集します。その後、専用の静的ファイルサーバーを使用してそれらのファイルを提供することで、通常、全体的なパフォーマンスが向上します。以下の手順は、この収集がどのように行われるかを示していますが、Django 開発サーバーで実行する場合は収集を使用しません。</p> <ol> <li> <p><code>web_project/settings.py</code> に、<code>collectstatic</code> コマンドを使用するときに静的ファイルが収集される場所を定義する次の行を追加します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">STATIC_ROOT = BASE_DIR / </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'static_collected'</span></span> <span class="line"></span></code></pre> </li> <li> <p>ターミナルで <code>python manage.py collectstatic</code> コマンドを実行し、<code>hello/site.css</code> が <code>manage.py</code> と並んで最上位の <code>static_collected</code> フォルダーにコピーされることを確認します。</p> </li> <li> <p>実際には、静的ファイルを変更するたびに、本番環境にデプロイする前に <code>collectstatic</code> を実行します。</p> </li> </ol> <h2 id="_create-multiple-templates-that-extend-a-base-template" data-needslink="_create-multiple-templates-that-extend-a-base-template">ベース テンプレートを拡張する複数のテンプレートを作成する</h2> <p>ほとんどの Web アプリには複数のページがあり、それらのページは通常、多くの共通要素を共有するため、開発者はそれらの共通要素をベースページテンプレートに分離し、他のページテンプレートがそれを拡張します。(これはテンプレート継承とも呼ばれ、拡張されたページはベースページから要素を継承することを意味します。)</p> <p>また、同じテンプレートを拡張する多くのページを作成する可能性が高いため、VS Code でコード スニペットを作成して、新しいページ テンプレートをすばやく初期化できるようにすると便利です。スニペットは、退屈でエラーが発生しやすいコピー&ペースト操作を回避するのに役立ちます。</p> <p>次のセクションでは、このプロセスのさまざまな部分について説明します。</p> <h3 id="_create-a-base-page-template-and-styles" data-needslink="_create-a-base-page-template-and-styles">ベース ページ テンプレートとスタイルを作成する</h3> <p>Django のベースページテンプレートには、CSS ファイルやスクリプトファイルなどへの参照を含む、一連のページの共有部分がすべて含まれています。ベーステンプレートは、拡張テンプレートがオーバーライドすることを期待する 1 つ以上の <strong>ブロック</strong> タグも定義します。ブロックタグは、ベーステンプレートと拡張テンプレートの両方で <code>{% block <name> %}</code> と <code>{% endblock %}</code> で区切られます。</p> <p>次の手順では、ベース テンプレートの作成方法を示します。</p> <ol> <li> <p><code>templates/hello</code> フォルダーに、以下の内容で <code>layout.html</code> というファイルを作成します。これには、「title」と「content」という名前のブロックが含まれています。ご覧のとおり、マークアップは、Home、About、Contact ページへのリンクを含むシンプルなナビゲーションバー構造を定義しており、これらは後のセクションで作成します。相対パスではなく、対応する URL パターンの名前を介して他のページを参照するために、Django の <code>{% url %}</code> タグが使用されていることに注目してください。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><!</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">DOCTYPE</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> html</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">html</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">head</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">meta</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> charset</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"utf-8"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">/></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">title</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% block title %}{% endblock %}</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">title</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% load static %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">link</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> rel</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"stylesheet"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> type</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"text/css"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% static 'hello/site.css' %}"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">/></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">head</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">body</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">div</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"navbar"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% url 'home' %}"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"navbar-brand"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Home</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% url 'about' %}"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"navbar-item"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">About</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% url 'contact' %}"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"navbar-item"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Contact</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">div</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">div</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"body-content"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% block content %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% endblock %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">hr</span><span style="--shiki-dark:#808080;--shiki-light:#800000">/></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">footer</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">p</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">&copy;</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> 2018</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">p</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">footer</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">div</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">body</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">html</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"></span></code></pre> </li> <li> <p>既存の「message」スタイルの下に次のスタイルを <code>static/hello/site.css</code> に追加し、ファイルを保存します。(このチュートリアルではレスポンシブデザインのデモンストレーションは試みません。これらのスタイルは単に、そこそこ興味深い結果を生成するだけです。)</p> <pre class="shiki" data-lang="css" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.navbar</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> background-color</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">lightslategray</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-size</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">1em</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-family</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'Trebuchet MS'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'Lucida Sans Unicode'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'Lucida Grande'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'Lucida Sans'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">Arial</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">sans-serif</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> color</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">white</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> padding</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">8px</span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658"> 5px</span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658"> 8px</span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658"> 5px</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.navbar</span><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000"> a</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> text-decoration</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">none</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> color</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">inherit</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.navbar-brand</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-size</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">1.2em</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-weight</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">600</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.navbar-item</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-variant</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">small-caps</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> margin-left</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">30px</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.body-content</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> padding</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">5px</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> font-family</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">:</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'Segoe UI'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">Tahoma</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, Geneva, </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">Verdana</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">sans-serif</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span></code></pre> </li> </ol> <p>現時点でもアプリを実行できますが、ベース テンプレートをどこでも使用しておらず、コード ファイルも変更していないため、結果は前の手順と同じになります。最終的な効果を確認するには、残りのセクションを完了してください。</p> <h3 id="_create-a-code-snippet" data-needslink="_create-a-code-snippet">コードスニペットを作成する</h3> <p>次のセクションで作成する 3 つのページはすべて <code>layout.html</code> を拡張するため、ベース テンプレートへの適切な参照で新しいテンプレート ファイルを初期化する <strong>コード スニペット</strong> を作成すると時間を節約できます。コード スニペットは、単一のソースから一貫性のあるコードを提供し、既存のコードからのコピー&ペーストを使用するときに忍び込む可能性のあるエラーを回避します。</p> <ol> <li> <p>VS Code で、<strong>ファイル</strong> (Windows/Linux) または <strong>コード</strong> (macOS) メニューを選択し、次に <strong>設定</strong> > <strong>ユーザー スニペット</strong> を選択します。</p> </li> <li> <p>表示されるリストで <strong>html</strong> を選択します。(以前にスニペットを作成している場合は、リストの <strong>既存のスニペット</strong> セクションに「html.json」として表示される場合があります。)</p> </li> <li> <p>VS Code で <code>html.json</code> が開いたら、既存の中括弧内に以下のコードを追加します。(ここでは示されていませんが、説明コメントには、<code>$0</code> 行がスニペットを挿入した後に VS Code がカーソルをどこに配置するかなどの詳細が記述されています。)</p> <pre class="shiki" data-lang="json" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"Django Tutorial: template extending layout.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#0451A5"> "prefix"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"djextlayout"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#0451A5"> "body"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: [</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "{% extends </span><span style="--shiki-dark:#D7BA7D;--shiki-light:#EE0000">\"</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">hello/layout.html</span><span style="--shiki-dark:#D7BA7D;--shiki-light:#EE0000">\"</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> %}"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "{% block title %}"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "$0"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "{% endblock %}"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "{% block content %}"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> "{% endblock %}"</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> ],</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#0451A5"> "description"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"Boilerplate template that extends layout.html"</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">},</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>html.json</code> ファイルを保存します (<span class="dynamic-keybinding" data-commandid="workbench.action.files.save" data-osx="⌘S" data-win="Ctrl+S" data-linux="Ctrl+S"><span class="keybinding">⌘S</span> (Windows, Linux <span class="keybinding">Ctrl+S</span>)</span>)。</p> </li> <li> <p>これで、次に示すように、スニペットのプレフィックス (例: <code>djext</code>) の入力を開始すると、VS Code がオートコンプリートオプションとしてスニペットを提供します。<strong>スニペットの挿入</strong> コマンドを使用して、メニューからスニペットを選択することもできます。</p> </li> </ol> <p>コード スニペット全般に関する詳細については、<a href="/docs/editing/userdefinedsnippets">スニペットの作成</a> を参照してください。</p> <h3 id="_use-the-code-snippet-to-add-pages" data-needslink="_use-the-code-snippet-to-add-pages">コードスニペットを使用してページを追加する</h3> <p>コード スニペットが用意できたので、ホーム、アバウト、コンタクト ページ用のテンプレートをすばやく作成できます。</p> <ol> <li> <p><code>templates/hello</code> フォルダーに <code>home.html</code> という名前の新しいファイルを作成し、<code>djext</code> の入力を開始してスニペットが完了として表示されることを確認します。</p> <p><img src="/assets/docs/python/django-tutorial/autocomplete-for-code-snippet.png" alt="Django tutorial: autocompletion for the djextlayout code snippet" loading="lazy"></p> <p>補完を選択すると、スニペットのコードがスニペットの挿入ポイントにカーソルを置いて表示されます</p> <p><img src="/assets/docs/python/django-tutorial/code-snippet-inserted.png" alt="Django tutorial: insertion of the djextlayout code snippet" loading="lazy"></p> </li> <li> <p>「title」ブロックの挿入ポイントに <code>Home</code> と書き込み、「content」ブロックに <code><p>Visual Studio Code Django チュートリアルのホームページです。</p></code> と書き込み、ファイルを保存します。これらの行が、拡張ページテンプレートの唯一のユニークな部分です。</p> </li> <li> <p><code>templates/hello</code> フォルダーに <code>about.html</code> を作成し、スニペットを使用して定型マークアップを挿入し、「title」と「content」ブロックにそれぞれ <code>About us</code> と <code><p>Visual Studio Code Django チュートリアルの about ページです。</p></code> を挿入し、ファイルを保存します。</p> </li> <li> <p>前の手順を繰り返して、<code>templates/hello/contact.html</code> を <code>Contact us</code> と <code><p>Visual Studio Code Django チュートリアルのコンタクトページです。</p></code> を使用して作成します。</p> </li> <li> <p>アプリの <code>urls.py</code> で、/about および /contact ページのルートを追加します。<code>path</code> 関数の <code>name</code> 引数は、テンプレートの <code>{% url %}</code> タグでページを参照する名前を定義していることに注意してください。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">path(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"about/"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, views.about, </span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"about"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">),</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">path(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"contact/"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, views.contact, </span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"contact"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">),</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>views.py</code> で、/about および /contact ルートに対応する関数を定義し、それぞれのページテンプレートを参照するようにします。また、<code>home</code> 関数を <code>home.html</code> テンプレートを使用するように変更します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># Replace the existing home function with the one below</span></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> home</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">request</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> render(request, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"hello/home.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> about</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">request</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> render(request, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"hello/about.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> contact</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">request</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> render(request, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"hello/contact.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span></code></pre> </li> </ol> <h3 id="_run-the-app" data-needslink="_run-the-app">アプリを実行する</h3> <p>すべてのページテンプレートが配置されたら、<code>views.py</code> を保存し、アプリを実行し、ブラウザでホーム​​ページを開いて結果を確認します。ページ間を移動して、ページテンプレートがベーステンプレートを正しく拡張していることを確認します。</p> <p><img src="/assets/docs/python/django-tutorial/full-app.png" alt="Django tutorial: app rendering a common nav bar from the base template" loading="lazy"></p> <h2 id="_work-with-data-data-models-and-migrations" data-needslink="_work-with-data-data-models-and-migrations">データ、データモデル、およびマイグレーションの操作</h2> <p>多くの Web アプリケーションはデータベースに保存された情報と連携しており、Django は、そのデータベース内のオブジェクトを <em>モデル</em> を使用して簡単に表現できます。Django では、モデルは <code>django.db.models.Model</code> から派生した Python クラスであり、特定のデータベースオブジェクト (通常はテーブル) を表します。これらのクラスは、アプリの <code>models.py</code> ファイルに配置します。</p> <p>Django では、コードで定義するモデルを通じて、ほぼ排他的にデータベースを操作します。Django の「マイグレーション」は、時間の経過とともにモデルが進化したときに、基になるデータベースのすべての詳細を自動的に処理します。一般的なワークフローは次のとおりです。</p> <ol> <li><code>models.py</code> ファイルのモデルを変更します。</li> <li><code>python manage.py makemigrations</code> を実行して、データベースを現在の状態から新しい状態に移行するスクリプトを <code>migrations</code> フォルダーに生成します。</li> <li><code>python manage.py migrate</code> を実行して、実際のデータベースにスクリプトを適用します。</li> </ol> <p>マイグレーションスクリプトは、データモデルに対して時間経過とともに加えられたすべての増分変更を効果的に記録します。マイグレーションを適用することで、Django はデータベースをモデルに合わせて更新します。各増分変更には独自のスクリプトがあるため、Django はデータベースの <em>どの</em> 以前のバージョン (新しいデータベースを含む) でも現在のバージョンに自動的に移行できます。結果として、<code>models.py</code> 内のモデルのみに関心を持ち、基盤となるデータベーススキーマやマイグレーションスクリプトについては気にする必要はありません。その部分は Django に任せてください!</p> <p>コードでも、モデルクラスのみを使用してデータを保存および取得します。Django が基盤となる詳細を処理します。唯一の例外は、Django 管理ユーティリティの <a href="https://docs.djangoproject.com/en/3.1/ref/django-admin/#loaddata" class="external-link" target="_blank">loaddata コマンド</a> を使用してデータベースにデータを書き込むことができることです。このユーティリティは、<code>migrate</code> コマンドがスキーマを初期化した後にデータセットを初期化するためによく使用されます。</p> <p><code>db.sqlite3</code> ファイルを使用する場合、<a href="https://sqlitebrowser.org/" class="external-link" target="_blank">SQLite browser</a> のようなツールを使用してデータベースを直接操作することもできます。そのようなツールを使用してテーブルのレコードを追加または削除しても問題ありませんが、データベーススキーマの変更は避けてください。そうしないと、データベースがアプリのモデルと同期しなくなります。代わりに、モデルを変更し、<code>makemigrations</code> を実行し、次に <code>migrate</code> を実行します。</p> <h3 id="_types-of-databases" data-needslink="_types-of-databases">データベースの種類</h3> <p>デフォルトでは、Django はアプリのデータベース用の <code>db.sqlite3</code> ファイルを含んでおり、これは開発作業に適しています。<a href="https://www.sqlite.org/whentouse.html" class="external-link" target="_blank">SQLite の使用時期</a> (sqlite.org) で説明されているように、SQLite は 1 日あたり 10 万ヒット未満の低トラフィックから中トラフィックのサイトでは問題なく機能しますが、それ以上のボリュームには推奨されません。また、単一のコンピューターに制限されているため、ロードバランシングや地理的レプリケーションなどのマルチサーバーシナリオでは使用できません。</p> <p>これらの理由から、<a href="https://www.postgresql.org/" class="external-link" target="_blank">PostgreSQL</a>、<a href="https://www.mysql.com/" class="external-link" target="_blank">MySQL</a>、<a href="https://www.microsoft.com/en-ca/sql-server/" class="external-link" target="_blank">SQL Server</a> などの本番レベルのデータストアの使用を検討してください。他のデータベースに対する Django のサポートに関する情報については、<a href="https://docs.djangoproject.com/en/3.1/intro/tutorial02/#database-setup" class="external-link" target="_blank">データベースの設定</a> を参照してください。また、<a href="https://learn.microsoft.com/azure/developer/python/sdk/azure-sdk-overview" class="external-link" target="_blank">Azure SDK for Python</a> を使用して、テーブルやBLOBなどの Azure ストレージサービスを操作することもできます。</p> <h3 id="_define-models" data-needslink="_define-models">モデルを定義する</h3> <p>Django モデルは、<code>django.db.model.Models</code> から派生した Python クラスであり、アプリの <code>models.py</code> ファイルに配置します。データベースでは、各モデルに <code>id</code> という一意の ID フィールドが自動的に付与されます。他のすべてのフィールドは、<code>django.db.models</code> からの型 (<code>CharField</code> (制限付きテキスト)、<code>TextField</code> (無制限テキスト)、<code>EmailField</code>、<code>URLField</code>、<code>IntegerField</code>、<code>DecimalField</code>、<code>BooleanField</code>。<code>DateTimeField</code>、<code>ForeignKey</code>、<code>ManyToMany</code> など) を使用してクラスのプロパティとして定義されます。(詳細については、Django ドキュメントの <a href="https://docs.djangoproject.com/en/3.1/ref/models/fields/" class="external-link" target="_blank">モデルフィールドリファレンス</a> を参照してください。)</p> <p>各フィールドには、<code>max_length</code> などの属性があります。<code>blank=True</code> 属性はフィールドがオプションであることを意味し、<code>null=true</code> は値がオプションであることを意味します。また、データ値/表示値タプルの配列内の値に値を制限する <code>choices</code> 属性もあります。</p> <p>たとえば、<code>models.py</code> に次のクラスを追加して、シンプルなメッセージログの日付付きエントリを表すデータモデルを定義します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> django.db </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> models</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> django.utils </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> timezone</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">class</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99"> LogMessage</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">models</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">.</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">Model</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> message = models.CharField(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">max_length</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">300</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> log_date = models.DateTimeField(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"date logged"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF"> def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> __str__</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">self</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> """Returns a string representation of a message."""</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> date = timezone.localtime(</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">self</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">.log_date)</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF"> f</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"'</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">{self</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">.message</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">}</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">' logged on </span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">{</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">date.strftime(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'%A, </span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">%d</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> %B, %Y at </span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">%X</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">'</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">}</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"</span></span> <span class="line"></span></code></pre> <p>モデルクラスには、他のクラスプロパティから計算された値を返すメソッドを含めることができます。モデルには通常、インスタンスの文字列表現を返す <code>__str__</code> メソッドが含まれています。</p> <h3 id="_migrate-the-database" data-needslink="_migrate-the-database">データベースを移行する</h3> <p><code>models.py</code> を編集してデータモデルを変更したため、データベース自体を更新する必要があります。VS Code で、仮想環境がアクティブ化されたターミナルを開き (<strong>ターミナル: 新しいターミナルを作成</strong> コマンド (<span class="dynamic-keybinding" data-commandid="workbench.action.terminal.new" data-osx="⌃⇧`" data-win="Ctrl+Shift+`" data-linux="Ctrl+Shift+`"><span class="keybinding">⌃⇧`</span> (Windows, Linux <span class="keybinding">Ctrl+Shift+`</span>)</span>) を使用)、プロジェクトフォルダーに移動して、次のコマンドを実行します。</p> <pre class="shiki" data-lang="bash" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26">python</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> manage.py</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> makemigrations</span></span> <span class="line"><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26">python</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> manage.py</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> migrate</span></span> <span class="line"></span></code></pre> <p><code>migrations</code> フォルダーで <code>makemigrations</code> が生成したスクリプトを確認します。データベース自体を調べて、スキーマが更新されていることも確認できます。</p> <p>コマンドの実行中にエラーが表示された場合は、以前のステップで残っているデバッグターミナルを使用していないことを確認してください。仮想環境がアクティブ化されていない可能性があります。</p> <h3 id="_use-the-database-through-the-models" data-needslink="_use-the-database-through-the-models">モデルを介してデータベースを使用する</h3> <p>モデルが配置され、データベースが移行されたので、モデルのみを使用してデータを保存および取得できます。このセクションでは、メッセージを記録できるフォームページをアプリに追加します。次に、それらのメッセージを表示するようにホームページを変更します。ここでは多くのコードファイルを変更するため、詳細に注意してください。</p> <ol> <li> <p><code>hello</code> フォルダー (<code>views.py</code> がある場所) に、次のコードで <code>forms.py</code> という新しいファイルを作成します。これは、データモデル <code>LogMessage</code> から取得されたフィールドを含む Django フォームを定義します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> django </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> forms</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> hello.models </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> LogMessage</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">class</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99"> LogMessageForm</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">forms</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">.</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">ModelForm</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF"> class</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99"> Meta</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">:</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> model = LogMessage</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> fields = (</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"message"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,) </span><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># </span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">NOTE</span><span style="--shiki-dark:#6A9955;--shiki-light:#008000">: the trailing comma is required</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>templates/hello</code> フォルダーに、以下の内容で <code>log_message.html</code> という新しいテンプレートを作成します。これは、テンプレートにフォームの本文を定義するための <code>form</code> という名前の変数が与えられていることを想定しています。次に、「Log」というラベルの付いた送信ボタンを追加します。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% extends "hello/layout.html" %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% block title %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> Log a message</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% endblock %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% block content %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">form</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> method</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"POST"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"log-form"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% csrf_token %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {{ form.as_p }}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">button</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> type</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"submit"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"save btn btn-default"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Log</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">button</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">form</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% endblock %}</span></span> <span class="line"></span></code></pre> <blockquote><p><strong>注</strong>: Django の <code>{% csrf_token %}</code> タグは、クロスサイトリクエストフォージェリからの保護を提供します。詳細については、Django ドキュメントの <a href="https://docs.djangoproject.com/en/3.1/ref/csrf/" class="external-link" target="_blank">クロスサイトリクエストフォージェリ保護</a> を参照してください。</p> </blockquote></li> <li> <p>アプリの <code>static/hello/site.css</code> ファイルに、入力フォームを広くするためのルールを追加します</p> <pre class="shiki" data-lang="css" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">input</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">[</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000">name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">message</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">] {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> width</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">80%</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span></code></pre> </li> <li> <p>アプリの <code>urls.py</code> ファイルに、新しいページのルートを追加します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">path(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"log/"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, views.log_message, </span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"log"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">),</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>views.py</code> で、<code>log_message</code> という名前のビューを定義します (URL ルートで参照されているとおり)。このビューは、HTTP GET と POST の両方のケースを処理します。GET の場合 (<code>else:</code> セクション)、前の手順で定義したフォームを表示するだけです。POST の場合、フォームからデータ (<code>message</code>) をデータオブジェクトに取得し、タイムスタンプを設定してから、そのオブジェクトを保存します。この時点で、データはデータベースに書き込まれます。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># Add these to existing imports at the top of the file:</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> django.shortcuts </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> redirect</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> hello.forms </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> LogMessageForm</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> hello.models </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> LogMessage</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># Add this code elsewhere in the file:</span></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> log_message</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">request</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> form = LogMessageForm(request.POST </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">or</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF"> None</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> if</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> request.method == </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"POST"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">:</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> if</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> form.is_valid():</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> message = form.save(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">commit</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">False</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> message.log_date = datetime.now()</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> message.save()</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> redirect(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"home"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> else</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">:</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> render(request, </span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"hello/log_message.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, {</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"form"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: form})</span></span> <span class="line"></span></code></pre> </li> <li> <p>すべてを試す準備が整う前に、もう 1 つ手順があります!<code>templates/hello/layout.html</code> で、メッセージログページへのリンクを「navbar」div に追加します。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"><!-- Insert below the link to Home --></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% url 'log' %}"</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"navbar-item"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Log Message</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"></span></code></pre> </li> <li> <p>アプリを実行し、ブラウザでホームページを開きます。ナビゲーションバーの <strong>メッセージをログ</strong> リンクを選択すると、メッセージログページが表示されるはずです。</p> <p><img src="/assets/docs/python/django-tutorial/message-logging-page.png" alt="Django tutorial: the message logging page added to the app" loading="lazy"></p> </li> <li> <p>メッセージを入力し、<strong>ログ</strong> を選択すると、ホームページに戻るはずです。ホームページにはまだログに記録されたメッセージが表示されません (これはすぐに修正します)。いくつかメッセージをログに記録しても構いません。必要に応じて、SQLite Browser のようなツールを使用してデータベースを覗き見して、レコードが作成されたことを確認してください。データベースを読み取り専用で開くか、アプリを使用する前にデータベースを閉じることを忘れないでください。そうしないと、データベースがロックされているためアプリが失敗します。</p> </li> <li> <p>作業が完了したら、アプリを停止します。</p> </li> <li> <p>次に、ホームページを変更して、ログに記録されたメッセージを表示します。まず、アプリの <code>templates/hello/home.html</code> ファイルの内容を以下のマークアップに置き換えます。このテンプレートは、<code>message_list</code> という名前のコンテキスト変数を想定しています。受け取った場合 (<code>{% if message_list %}</code> タグで確認)、そのリストを反復処理して (<code>{% for message in message_list %}</code> タグ)、各メッセージのテーブル行を生成します。それ以外の場合、ページにはまだメッセージがログに記録されていないことが示されます。</p> <pre class="shiki" data-lang="html" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% extends "hello/layout.html" %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% block title %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> Home</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% endblock %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% block content %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">h2</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Logged messages</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">h2</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% if message_list %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">table</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> class</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"message_list"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">thead</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tr</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Date</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Time</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Message</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">th</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tr</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">thead</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tbody</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% for message in message_list %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tr</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{{ message.log_date | date:'d M Y' }}</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{{ message.log_date | time:'H:i:s' }}</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {{ message.message }}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">td</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tr</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% endfor %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">tbody</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> </</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">table</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% else %}</span></span> <span class="line"><span style="--shiki-dark:#808080;--shiki-light:#800000"> <</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">p</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">No messages have been logged. Use the </span><span style="--shiki-dark:#808080;--shiki-light:#800000"><</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> href</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#0000FF">"{% url 'log' %}"</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">Log Message form</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">a</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">.</span><span style="--shiki-dark:#808080;--shiki-light:#800000"></</span><span style="--shiki-dark:#569CD6;--shiki-light:#800000">p</span><span style="--shiki-dark:#808080;--shiki-light:#800000">></span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {% endif %}</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">{% endblock %}</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>static/hello/site.css</code> に、テーブルを少し整形するためのルールを追加します。</p> <pre class="shiki" data-lang="css" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">.message_list</span><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000"> th</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span><span style="--shiki-dark:#D7BA7D;--shiki-light:#800000">td</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> {</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> text-align</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#CE9178;--shiki-light:#0451A5">left</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#E50000"> padding-right</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">: </span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">15px</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">;</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">}</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>views.py</code> で、Django の汎用 <code>ListView</code> クラスをインポートします。これは、ホームページを実装するために使用します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> django.views.generic </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> ListView</span></span> <span class="line"></span></code></pre> </li> <li> <p>また、<code>views.py</code> で、<code>home</code> 関数を <code>ListView</code> から派生した <code>HomeListView</code> という名前の <em>クラス</em> に置き換えます。このクラスは、<code>LogMessage</code> モデルにバインドされ、テンプレートのコンテキストを生成する <code>get_context_data</code> 関数を実装します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># Remove the old home function if you want; it's no longer used</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">class</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99"> HomeListView</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">ListView</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#CE9178;--shiki-light:#A31515"> """Renders the home page, with a list of all messages."""</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> model = LogMessage</span></span> <span class="line"></span> <span class="line"><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF"> def</span><span style="--shiki-dark:#DCDCAA;--shiki-light:#795E26"> get_context_data</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">self</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, **</span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">kwargs</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">):</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> context = </span><span style="--shiki-dark:#4EC9B0;--shiki-light:#267F99">super</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">(HomeListView, </span><span style="--shiki-dark:#569CD6;--shiki-light:#0000FF">self</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">).get_context_data(**kwargs)</span></span> <span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB"> return</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> context</span></span> <span class="line"></span></code></pre> </li> <li> <p>アプリの <code>urls.py</code> で、データモデルをインポートします。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">from</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> hello.models </span><span style="--shiki-dark:#C586C0;--shiki-light:#AF00DB">import</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> LogMessage</span></span> <span class="line"></span></code></pre> </li> <li> <p>また、<code>urls.py</code> で、新しいビューの変数を設定します。これは、最新の <code>LogMessage</code> オブジェクトを降順で 5 つ取得し (つまり、データベースをクエリし)、テンプレートコンテキストでデータの名前 (<code>message_list</code>) を提供し、使用するテンプレートを識別します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">home_list_view = views.HomeListView.as_view(</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080"> queryset</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=LogMessage.objects.order_by(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"-log_date"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)[:</span><span style="--shiki-dark:#B5CEA8;--shiki-light:#098658">5</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">], </span><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># :5 limits the results to the five most recent</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080"> context_object_name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"message_list"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080"> template_name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"hello/home.html"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">,</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">)</span></span> <span class="line"></span></code></pre> </li> <li> <p><code>urls.py</code> で、ホームページへのパスを <code>home_list_view</code> 変数を使用するように変更します。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"> # Replace the existing path for ""</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> path(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">""</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, home_list_view, </span><span style="--shiki-dark:#9CDCFE;--shiki-light:#001080">name</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">=</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"home"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">),</span></span> <span class="line"></span></code></pre> </li> <li> <p>アプリを起動し、ブラウザでホームページを開くと、メッセージが表示されるはずです。</p> <p><img src="/assets/docs/python/django-tutorial/app-with-message-list.png" alt="Django tutorial: app home page displaying message from the database" loading="lazy"></p> </li> <li> <p>作業が完了したら、アプリを停止します。</p> </li> </ol> <h2 id="_use-the-debugger-with-page-templates" data-needslink="_use-the-debugger-with-page-templates">ページテンプレートでデバッガーを使用する</h2> <p>前のセクションで示したように、ページテンプレートは <code>{% url %}</code> や <code>{% block %}</code> のような受動的で宣言的な要素だけでなく、<code>{% for message in message_list %}</code> や <code>{% if message_list %}</code> のような手続き型ディレクティブを含めることができます。その結果、他の手続き型コードと同様に、テンプレート内にもプログラミングエラーが発生する可能性があります。</p> <p>幸いなことに、VS Code 用の Python 拡張機能は、デバッグ構成に <code>"django": true</code> がある場合 (すでにそうですが) にテンプレートデバッグを提供します。次の手順でこの機能を示します。</p> <ol> <li> <p><code>templates/hello/home.html</code> で、以下の画像にある黄色の矢印で示されているように、<code>{% if message_list %}</code> と <code>{% for message in message_list %}</code> の両方の行にブレークポイントを設定します。</p> <p><img src="/assets/docs/python/django-tutorial/template-breakpoints.png" alt="Django tutorial: breakpoints set in a Django page template" loading="lazy"></p> </li> <li> <p>デバッガーでアプリを実行し、ブラウザでホームページを開きます。(すでにデバッガーを実行している場合は、ブレークポイントを設定した後にアプリを再起動する必要はありません。ページを更新するだけです。) VS Code がテンプレートの <code>{% if %}</code> ステートメントでデバッガーにブレークインし、<strong>変数</strong> ペインにすべてのコンテキスト変数が表示されることを確認します。</p> <p><img src="/assets/docs/python/django-tutorial/template-debugger.png" alt="Django tutorial: debugger stopped at breakpoints in the page template" loading="lazy"></p> </li> <li> <p>ステップオーバー (<span class="dynamic-keybinding" data-commandid="workbench.action.debug.stepOver" data-osx="F10" data-win="F10" data-linux="F10"><span class="keybinding">F10</span></span>) コマンドを使用して、テンプレートコードをステップ実行します。すべての宣言ステートメントをスキップし、任意の手続き型コードで一時停止することを確認します。たとえば、<code>{% for message in message_list %}</code> ループをステップ実行すると、<code>message</code> の各値を調べ、<code><td>{{ message.log_date | date:'d M Y' }}</td></code> のような行にステップ実行できます。</p> </li> <li> <p><strong>デバッグコンソール</strong> パネルで変数と連携することもできます。(ただし、<code>date</code> のような Django フィルターは現在コンソールでは利用できません。)</p> </li> <li> <p>準備ができたら、続行 (<span class="dynamic-keybinding" data-commandid="workbench.action.debug.continue" data-osx="F5" data-win="F5" data-linux="F5"><span class="keybinding">F5</span></span>) を選択してアプリの実行を終了し、レンダリングされたページをブラウザで表示します。終了したらデバッガーを停止します。</p> </li> </ol> <h2 id="_optional-activities" data-needslink="_optional-activities">オプションのアクティビティ</h2> <p>以下のセクションでは、Python および Visual Studio Code を使用する際に役立つ可能性のある追加の手順について説明します。</p> <h3 id="_create-a-requirementstxt-file-for-the-environment" data-needslink="_create-a-requirementstxt-file-for-the-environment">環境の requirements.txt ファイルを作成する</h3> <p>ソース管理やその他の手段でアプリコードを共有する場合、仮想環境内のすべてのファイルをコピーすることは意味がありません。なぜなら、受け取った人がいつでも自分でその環境を再作成できるからです。</p> <p>したがって、開発者は通常、仮想環境フォルダーをソース管理から除外し、代わりに <code>requirements.txt</code> ファイルを使用してアプリの依存関係を記述します。</p> <p>手動でファイルを作成することもできますが、<code>pip freeze</code> コマンドを使用して、アクティブ化された環境にインストールされている正確なライブラリに基づいてファイルを生成することもできます</p> <ol> <li> <p><strong>Python: インタープリターを選択</strong> コマンドを使用して選択した環境で、<strong>ターミナル: 新しいターミナルを作成</strong> コマンド (<span class="dynamic-keybinding" data-commandid="workbench.action.terminal.new" data-osx="⌃⇧`" data-win="Ctrl+Shift+`" data-linux="Ctrl+Shift+`"><span class="keybinding">⌃⇧`</span> (Windows, Linux <span class="keybinding">Ctrl+Shift+`</span>)</span>)) を実行して、その環境がアクティブ化されたターミナルを開きます。</p> </li> <li> <p>ターミナルで <code>pip freeze > requirements.txt</code> を実行して、プロジェクト フォルダーに <code>requirements.txt</code> ファイルを作成します。</p> </li> </ol> <p>プロジェクトのコピーを受け取る人 (またはビルドサーバー) は、<code>pip install -r requirements.txt</code> コマンドを実行するだけで、アクティブな環境でアプリが依存するパッケージを再インストールできます。</p> <blockquote><p><strong>注</strong>: <code>pip freeze</code> は、現在使用していないパッケージを含む、現在の環境にインストールされているすべての Python パッケージを一覧表示します。このコマンドは、正確なバージョン番号を持つパッケージも一覧表示しますが、将来的に柔軟性を高めるために範囲に変換したい場合があります。詳細については、pip コマンドのドキュメントにある <a href="https://pip.dokyumento.jp/en/stable/user_guide/#requirements-files" class="external-link" target="_blank">要件ファイル</a> を参照してください。</p> </blockquote><h3 id="_create-a-superuser-and-enable-the-administrative-interface" data-needslink="_create-a-superuser-and-enable-the-administrative-interface">スーパーユーザーを作成し、管理インターフェースを有効にする</h3> <p>デフォルトでは、Django は認証によって保護された Web アプリの管理インターフェースを提供します。このインターフェースは、プロジェクトの <code>INSTALLED_APPS</code> リスト (<code>settings.py</code>) にデフォルトで含まれている組み込みの <code>django.contrib.admin</code> アプリを通じて実装されており、認証は、同じく <code>INSTALLED_APPS</code> にデフォルトで含まれている組み込みの <code>django.contrib.auth</code> アプリによって処理されます。</p> <p>管理インターフェースを有効にするには、次の手順を実行します。</p> <ol> <li> <p>仮想環境用の VS Code のターミナルを開き、次にコマンド <code>python manage.py createsuperuser --username=<username> --email=<email></code> を実行して、アプリにスーパーユーザーアカウントを作成します。もちろん、<code><username></code> と <code><email></code> はあなたの個人情報に置き換えます。コマンドを実行すると、Django はパスワードの入力と確認を求めます。</p> <p>ユーザー名とパスワードの組み合わせを忘れないようにしてください。これらは、アプリで認証するために使用する資格情報です。</p> </li> <li> <p>プロジェクトレベルの <code>urls.py</code> (このチュートリアルでは <code>web_project/urls.py</code>) に次の URL ルートを追加して、組み込みの管理インターフェースを指すようにします。</p> <pre class="shiki" data-lang="python" shiki-themes="" dark-plus="" light-plus"="" style="--shiki-dark:#D4D4D4;--shiki-light:#000000;--shiki-dark-bg:#1E1E1E;--shiki-light-bg:#FFFFFF" tabindex="0"><code><span class="line"><span style="--shiki-dark:#6A9955;--shiki-light:#008000"># This path is included by default when creating the app</span></span> <span class="line"><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000"> path(</span><span style="--shiki-dark:#CE9178;--shiki-light:#A31515">"admin/"</span><span style="--shiki-dark:#D4D4D4;--shiki-light:#000000">, admin.site.urls),</span></span> <span class="line"></span></code></pre> </li> <li> <p>サーバーを実行し、ブラウザでアプリの /admin ページを開きます (開発サーバーを使用している場合は <code>http://127.0.0.1:8000/admin</code> など)。</p> </li> <li> <p><code>django.contrib.auth</code> によってログインページが表示されます。スーパーユーザーの資格情報を入力します。</p> <p><img src="/assets/docs/python/django-tutorial/login-prompt.png" alt="Django tutorial: default Django login prompt" loading="lazy"></p> </li> <li> <p>認証されると、ユーザーとグループを管理できるデフォルトの管理ページが表示されます。</p> <p><img src="/assets/docs/python/django-tutorial/default-admin-interface.png" alt="Django tutorial: the default Django administrative interface" loading="lazy"></p> </li> </ol> <p>管理インターフェースは好きなだけカスタマイズできます。たとえば、データベース内のエントリを編集および削除する機能を提供できます。カスタマイズの詳細については、<a href="https://docs.djangoproject.com/en/3.1/ref/contrib/admin/" class="external-link" target="_blank">Django 管理サイトのドキュメント</a> を参照してください。</p> <h3 id="_create-a-container-for-a-django-app-using-the-container-tools-extension" data-needslink="_create-a-container-for-a-django-app-using-the-container-tools-extension">Container Tools 拡張機能を使用して Django アプリのコンテナを作成する</h3> <p><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers" class="external-link" target="_blank">Container Tools 拡張機能</a> を使用すると、Visual Studio Code からコンテナ化されたアプリケーションを簡単に構築、管理、デプロイできます。このチュートリアルで開発した Django アプリ用の Python コンテナを作成する方法に興味がある場合は、<a href="/docs/containers/quickstart-python">コンテナ内の Python</a> チュートリアルをご覧ください。これは、次の方法を説明します。</p> <ul> <li>シンプルな Python コンテナーを記述する <code>Dockerfile</code> ファイルを作成する。</li> <li><a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> アプリの機能を構築、実行、検証します。</li> <li>コンテナーで実行されているアプリをデバッグする。</li> </ul> <h2 id="_next-steps" data-needslink="_next-steps">次のステップ</h2> <p>Visual Studio Code での Django の操作に関するこのチュートリアルを完了おめでとうございます!</p> <p>このチュートリアルで完成したコードプロジェクトは GitHub で見つけることができます: <a href="https://github.com/microsoft/python-sample-vscode-django-tutorial" class="external-link" target="_blank">python-sample-vscode-django-tutorial</a>。</p> <p>このチュートリアルでは、Django ができることのごく一部しか触れていません。ビュー、テンプレート、データモデル、URL ルーティング、管理インターフェース、他の種類のデータベースの使用、本番環境へのデプロイなどに関する詳細については、<a href="https://docs.djangoproject.com/en/3.1/" class="external-link" target="_blank">Django ドキュメント</a> および <a href="https://docs.djangoproject.com/en/3.1/intro/tutorial01/" class="external-link" target="_blank">公式 Django チュートリアル</a> を必ず参照してください。</p> <p>アプリを実稼働 Web サイトで試すには、チュートリアル <a href="https://learn.microsoft.com/azure/developer/python/tutorial-deploy-containers-01" class="external-link" target="_blank">Docker コンテナーを使用して Azure App Service に Python アプリをデプロイする</a> を確認してください。Azure には、標準コンテナーである <a href="https://learn.microsoft.com/azure/developer/python/configure-python-web-app-local-environment" class="external-link" target="_blank">Linux の App Service</a> もあり、VS Code 内から Web アプリをデプロイできます。</p> <p>Python に関連する VS Code ドキュメントの以下の記事も確認することをお勧めします</p> <ul> <li><a href="/docs/python/editing">Python コードの編集</a></li> <li><a href="/docs/python/linting">Linting</a></li> <li><a href="/docs/python/environments">Python 環境の管理</a></li> <li><a href="/docs/python/debugging">Python のデバッグ</a></li> <li><a href="/docs/python/testing">テスト</a></li> </ul> <div class="feedback"></div> <div class="body-footer">10/09/2025</div> </main> <!-- medium right nav --> <div class="col-sm-3 col-md-2 hidden-xs docs-subnavbar-container"> <nav id="docs-subnavbar" aria-label="On Page" data-spy="affix" data-offset-top="20"> <h4><span class="sr-only">このページには 13 のセクションがあります</span><span aria-hidden="true">このページ</span></h4> <ul class="nav"> <li><a href="#_prerequisites">前提条件</a></li> <li><a href="#_create-a-project-environment-for-the-django-tutorial">Django チュートリアルのプロジェクト環境を作成する</a></li> <li><a href="#_create-and-run-a-minimal-django-app">最小限の Django アプリを作成して実行する</a></li> <li><a href="#_create-a-debugger-launch-profile">デバッガー起動プロファイルを作成する</a></li> <li><a href="#_explore-the-debugger">デバッガーを探索する</a></li> <li><a href="#_go-to-definition-and-peek-definition-commands">定義へ移動および定義をピーク コマンド</a></li> <li><a href="#_use-a-template-to-render-a-page">テンプレートを使用してページをレンダリングする</a></li> <li><a href="#_serve-static-files">静的ファイルを配信する</a></li> <li><a href="#_create-multiple-templates-that-extend-a-base-template">ベース テンプレートを拡張する複数のテンプレートを作成する</a></li> <li><a href="#_work-with-data-data-models-and-migrations">データ、データモデル、およびマイグレーションの操作</a></li> <li><a href="#_use-the-debugger-with-page-templates">ページテンプレートでデバッガーを使用する</a></li> <li><a href="#_optional-activities">オプションのアクティビティ</a></li> <li><a href="#_next-steps">次のステップ</a></li> </ul> <div class="connect-widget"></div> </nav> </div> <!-- end of page connect widget --> <div class="col-xs-12 visible-xs"> <div class="connect-widget"></div> </div> </div> </div> </div> </div> <footer role="contentinfo" class="container"> <div class="footer-container"> <div class="footer-row"> <div class="footer-social"> <ul class="links"> <li> <a href="https://github.com/microsoft/vscode"><img src="/assets/icons/github-icon.svg" alt="VS Code on Github"></a> </li> <li> <a href="https://go.microsoft.com/fwlink/?LinkID=533687"><img src="/assets/icons/x-icon.svg" class="x-icon" alt="Follow us on X"></a> </li> <li> <a href="https://www.linkedin.com/showcase/vs-code"><img src="/assets/icons/linkedin-icon.svg" alt="VS Code on LinkedIn"></a> </li> <li> <a href="https://bsky.app/profile/vscode.dev"><img src="/assets/icons/bluesky-icon.svg" alt="VS Code on Bluesky"></a> </li> <li> <a href="https://www.reddit.com/r/vscode/"><img src="/assets/icons/reddit-icon.svg" alt="Join the VS Code community on Reddit"></a> </li> <li> <a href="https://www.vscodepodcast.com"><img src="/assets/icons/podcast-icon.svg" alt="The VS Code Insiders Podcast"></a> </li> <li> <a href="https://www.tiktok.com/@vscode"><img src="/assets/icons/tiktok-icon.svg" alt="VS Code on TikTok"></a> </li> <li> <a href="https://www.youtube.com/@code"><img src="/assets/icons/youtube-icon.svg" alt="VS Code on YouTube"></a> </li> <script> function manageConsent() { if (siteConsent && siteConsent.isConsentRequired) { siteConsent.manageConsent(); } } </script> </ul> <a id="footer-microsoft-link" class="microsoft-logo" href="https://www.microsoft.com"> <img src="/assets/icons/microsoft.svg" alt="Microsoft homepage"> </a> </div> </div> <div class="footer-row"> <ul class="links"> <li><a id="footer-support-link" href="https://support.serviceshub.microsoft.com/supportforbusiness/create?sapId=d66407ed-3967-b000-4cfb-2c318cad363d" target="_blank" rel="noopener">サポート</a></li> <li><a id="footer-privacy-link" href="https://go.microsoft.com/fwlink/?LinkId=521839" target="_blank" rel="noopener">プライバシー</a></li> <li style="display: none;"><a id="footer-cookie-link" style="cursor: pointer;" onclick="manageConsent()" target="_blank" rel="noopener">Cookieを管理</a></li> <li><a id="footer-terms-link" href="https://www.microsoft.com/legal/terms-of-use" target="_blank" rel="noopener">利用規約</a></li> <li><a id="footer-license-link" href="/License" target="_blank" rel="noopener">ライセンス</a></li> </ul> </div> </div> </footer> <script type="module"> document.addEventListener('DOMContentLoaded', () => { const copilotDeepLinks = document.querySelectorAll('.copilot-deep-link'); if (copilotDeepLinks.length === 0) { return; } if (window.innerWidth < 992) { for (const link of copilotDeepLinks) { link.href = 'https://aka.ms/vscode-activatecopilotfree'; } } }); </script> <script src="/dist/index.js"></script> <script type="application/ld+json"> { "@context" : "http://schema.org", "@type" : "SoftwareApplication", "name" : "Visual Studio Code", "softwareVersion": "1.105", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }, "applicationCategory": "DeveloperApplication", "applicationSubCategory": "Text Editor", "alternateName": "VS Code", "datePublished": "2021-11-03", "operatingSystem": "Mac, Linux, Windows", "logo": "https://vscode.dokyumento.jp/assets/apple-touch-icon.png", "screenshot": "https://vscode.dokyumento.jp/assets/home/home-screenshot-win.png", "releaseNotes": "https://vscode.dokyumento.jp/updates", "downloadUrl": "https://vscode.dokyumento.jp/download", "license": "https://vscode.dokyumento.jp/license", "softwareRequirements": "https://vscode.dokyumento.jp/docs/supporting/requirements", "url" : "https://vscode.dokyumento.jp", "author": { "@type": "Organization", "name": "Microsoft" }, "publisher": { "@type": "Organization", "name": "Microsoft" }, "maintainer": { "@type": "Organization", "name": "Microsoft" }, "potentialAction": { "@type": "SearchAction", "target": "https://vscode.dokyumento.jp/Search?q={search_term_string}", "query-input": "required name=search_term_string" }, "sameAs" : [ "https://en.wikipedia.org/wiki/Visual_Studio_Code", "https://twitter.com/code", "https://www.youtube.com/code", "https://www.tiktok.com/@vscode", "https://github.com/microsoft/vscode" ] } </script> <div style="padding: 3em 1em 6em; text-align: center;"> © <script>document.write(new Date().getFullYear())</script> <i><script>document.write(location.host)</script></i>. This site is unofficial and not affiliated with Microsoft. </div></body></html>