Django のチュートリアルメモ[書きかけ]
本ページはDjangoのチュートリアルをGPTを用いて自分向けに整理したメモになります。
Djangoを初めて使いたい!という人は、是非以下リンクの公式チュートリアルを参考にしてみてください。
公式チュートリアルリンク
1.Djangoをインストールする
python -m pip install Django
2.プロジェクトを作成する
Djangoは必要なプロジェクトファイルを生成する必要があり、このプロセスは
django-admin startproject mysite
によって簡単に実行されます。
このコマンドはDjangoのプロジェクトを作成し、プロジェクトの基盤となるファイルとディレクトリ構造を自動的に生成します。具体的には、以下の要素が生成されます。
ファイルは以下のように生成されます。
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
外側の mysite/ ディレクトリ:
このディレクトリはプロジェクトのコンテナとして機能し、プロジェクト全体を包括します。Django自体にとってこの名前は重要ではなく、開発者のニーズに合わせて任意に変更可能です。
manage.py:
これはDjangoプロジェクトに対する様々なコマンドを実行するためのコマンドラインユーティリティです。データベースのマイグレーションの適用、開発用サーバーの起動など、プロジェクトの管理に必要な多くの操作がこのスクリプトを通じて実行可能です。
内側の mysite/ ディレクトリ:
このディレクトリはプロジェクトの実際のPythonパッケージです。プロジェクト内でアプリケーション間でファイルをインポートする際にこの名前を使用します。
mysite/__init__.py:
この空のファイルはディレクトリがPythonのパッケージであることをPythonに通知します。これにより、プロジェクト内の他のファイルからこのディレクトリ内のモジュールをインポートすることが可能になります。
mysite/settings.py:
このファイルはDjangoプロジェクトの設定を保持します。データベースの設定、セキュリティの設定、アプリケーションの設定など、プロジェクト全体の動作に関わる多くの設定がここに含まれます。
mysite/urls.py:
このファイルはプロジェクトのURL宣言を含み、Djangoサイトの「目次」に相当します。URLパターンとビューをマッピングして、サイトのURL構造を定義します。
mysite/asgi.py:
このファイルは、ASGI(Asynchronous Server Gateway Interface)互換のWebサーバーを使用してプロジェクトをデプロイする際のエントリポイントとして機能します。非同期サーバーゲートウェイインターフェース(ASGI)は、Djangoが非同期ウェブアプリケーションをサポートするためのものです。
目的:
ASGIは、WSGIの非同期版として開発され、非同期Python Webフレームワーク(例えば、Django Channels)とWebサーバー間の標準インターフェースを提供します。asgi.pyは、非同期WebサーバーとDjangoアプリケーション間のエントリポイントとして機能します。
機能:
ASGIは、非同期I/Oをサポートし、WebSocketなどの長時間実行される接続や、リアルタイム機能を必要とするアプリケーションに適しています。これにより、同時に多数の接続を効率的に処理できます。
使用シナリオ:
高い同時接続数を持つアプリケーションや、リアルタイムの機能(例えば、チャットアプリやリアルタイム通知)を提供するアプリケーションに適しています。非同期プログラミングを利用することで、各リクエストや接続が個別のスレッドやプロセスによって処理されるのではなく、イベントループによって効率的に処理されます。
mysite/wsgi.py:
このファイルは、WSGI(Web Server Gateway Interface)互換のWebサーバーと連携してDjangoプロジェクトを提供する際のエントリポイントです。Webサーバーゲートウェイインターフェース(WSGI)は、PythonアプリケーションとWebサーバー間の標準インターフェースを提供します。
目的:
WSGIは、Pythonアプリケーション(特にDjangoやFlaskなどのWebフレームワーク)をWebサーバーと連携させるための標準インターフェースです。wsgi.pyは、DjangoアプリケーションとWSGI互換Webサーバー間のエントリポイントとして機能します。
機能:
Webサーバー(例えば、ApacheやNginxといったサーバーにmod_wsgiやuWSGIなどのモジュールを組み込むことで)は、HTTPリクエストを受け取り、それをWSGIプロトコルに従ってDjangoアプリケーションに渡します。wsgi.pyは、これらのリクエストをDjangoアプリケーションにルーティングする役割を果たします。
使用シナリオ:
主に同期的なアプリケーションに使用され、リクエストごとに1つのスレッドやプロセスが割り当てられます。これは、長時間実行されるリクエストや、リアルタイムでの多数の同時接続を扱う場合には最適ではないかもしれません。
3.開発用サーバの起動と管理
開発用サーバの起動
あなたのDjangoプロジェクトが正しくセットアップされているか確認する最初のステップは、開発用サーバを起動することです。これにより、アプリケーションの開発とテストをローカル環境で行うことができます。以下の手順に従って、サーバを起動しましょう。
コマンドの実行:
プロジェクトのルートディレクトリ(外側の mysite ディレクトリ)に移動し、以下のコマンドを実行して開発用サーバを起動してください。
$ python manage.py runserver
サーバの起動確認:
コマンドを実行すると、以下のような出力がコマンドラインに表示されます。
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
February 01, 2024 - 15:50:53
Django version 5.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
開発用サーバの特徴と注意点
軽量なWebサーバ:
Djangoに含まれる開発用サーバはPythonだけで書かれており、迅速な開発とテストを可能にするためのものです。Apacheのような運用サーバの設定を行う必要がないため、開発プロセスがスムーズに進みます。
安全上の注意:
開発用サーバは、開発段階での利用に特化して設計されています。運用環境での使用は厳禁です。セキュリティやパフォーマンスの面で、専門的なWebサーバを使用することが推奨されます。
サーバアクセスとポートのカスタマイズ
デフォルトアクセス:
ブラウザで `http://127.0.0.1:8000/` にアクセスすると、「Congratulations!」というメッセージとともに、ロケットが離陸しているページが表示されます。
ポート番号の変更:
デフォルトではポート8000で起動しますが、ポート番号を変更するには、次のようにコマンドライン引数を指定します。例えば、ポート8080で起動させたい場合は以下のようにします。
$ python manage.py runserver 8080
外部からのアクセス許可:
サーバを他のコンピュータからアクセス可能にするには、0.0.0.0を指定し、必要なポート番号を指定します。
$ python manage.py runserver 0.0.0.0:8000
自動リロード
開発サーバはPythonコードの変更を検知し、必要に応じて自動的にリロードします。これにより、コードの変更がすぐに反映され、開発プロセスがより迅速かつ効率的になります。ただし、ファイルの追加など一部の操作は自動リロードをトリガーしません。この場合は、サーバを手動で再起動する必要があります。
4.Pollsアプリケーションの作成
Djangoプロジェクト内に新しいアプリケーション、「Polls」を作成し、その基本的な構造を設定する方法を紹介します。Djangoでは、アプリケーションは特定の機能を提供する再利用可能なコンポーネントです。プロジェクトはこれらのアプリケーションを組み合わせて、完全なWebサイトを構築します。
4A.アプリケーションとプロジェクトの違い
アプリ: 独立した機能を持つWebアプリケーション(例: ブログシステム、投票アプリ)。
プロジェクト: 複数のアプリと追加の設定からなる、特定のWebサイト全体の構成。
アプリは複数のプロジェクトに含まれることができ、プロジェクトは複数のアプリを含むことができます。
4B.Pollsアプリケーションの作成
4B-1.コマンドの実行:
プロジェクトのルートディレクトリ(manage.pyがある場所)に移動し、以下のコマンドを実行して「Polls」アプリケーションを作成します。
$ python manage.py startapp polls
4B-2.ディレクトリ構造の確認:
上記のコマンドを実行すると、pollsという名前の新しいディレクトリが作成され、以下のような構造を持つことになります。
polls/
__init__.py # Pythonにこのディレクトリがパッケージであることを示す
admin.py # 管理サイト用の設定ファイル
apps.py # アプリの設定
migrations/ # データベースのマイグレーションを管理
__init__.py
models.py # データモデル
tests.py # テストスクリプト
views.py # ビュー(リクエストに対するロジックとレスポンスを定義)
これでPollsアプリケーションの基本的な骨格ができました。
5.はじめてのビューの作成
Pollsアプリケーションの中で最初のビューを作成し、それをWebページとして表示する方法について説明します。ビューはDjangoアプリケーションの「V」であり、リクエストに対するレスポンスを生成します。ここでは、シンプルなビューを作成し、それに対応するURLを設定する手順を学びます。
5A.最初のビューの作成
5A-1.ビューのコーディング:
polls/views.pyファイルを開き、以下のPythonコードを追加します。
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
これはDjangoで最もシンプルなビューで、リクエストを受け取り、HttpResponseオブジェクトを返します。
5A-1A.ビューのコーディング詳細解説
Djangoにおけるビューは、Webリクエストに対して何らかのレスポンスを返す関数またはクラスです。ビューの主な役割は、リクエストに含まれる情報を処理し、それに対するHTTPレスポンスを生成することです。以下では、最も基本的な形式のビューの作成方法とその動作について詳しく説明します。
ビューの作成
ビュー関数の定義:
ビューはviews.pyファイル内に関数として定義します。以下の例では、indexという名前のビュー関数を定義しています。
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
2.ビュー関数の引数:
ビュー関数は少なくとも一つの引数を取ります。通常はrequestと呼ばれ、リクエストに関する情報が含まれたHttpRequestオブジェクトです。
3.HttpResponseオブジェクトの生成:
ビューはHttpResponseオブジェクトを返します。このオブジェクトには、レスポンスとしてクライアントに送り返す内容が含まれます。
例では"Hello, world. You're at the polls index."というテキストを含むHttpResponseオブジェクトを作成しています。
ビューの動作
ユーザーがWebブラウザで特定のURLにアクセスすると、DjangoはそのURLに対応するビュー関数を探し、見つかったビュー関数を実行します。このとき、ユーザーのリクエストに関する情報がビュー関数にrequestオブジェクトとして渡されます。
ビュー関数は、リクエストに基づいて何らかの処理を行い、最終的にはHttpResponseオブジェクトを作成して返します。このHttpResponseオブジェクトに含まれる内容(この例では単純なテキストメッセージ)が、ユーザーのブラウザに表示されます。
このシンプルなビューでは、特定のURLにアクセスした際に、単純なテキストメッセージをユーザーに表示することができます。Djangoのビューはこのように、リクエストを受け取り、レスポンスを生成するための中心的な場所です。ビューの内部ではデータベースの読み書き、ユーザー認証の処理、他のサービスへのリクエストなど、より複雑な処理を行うことが可能です。
5A-2.URLの設定:
ビューにアクセスするためには、URLをビューにマッピングする必要があります。これを行うためにはURLconf(URL設定)が必要です。
5A-3.PollsアプリのURLconf作成:
pollsディレクトリにurls.pyファイルを新規作成し、以下のコードを書いてください
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
]
これにより、PollsアプリのルートURL("")がindexビューにマッピングされます。
5A-4.プロジェクトのURLconfの編集:
mysite/urls.pyファイルを開き、PollsアプリのURLconfを含めるように変更します。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("polls/", include("polls.urls")),
path("admin/", admin.site.urls),
]
include()関数は、他のURLconfへの参照を可能にします。ここでは"polls/"というパスにPollsアプリのURLconfを含めています。
5B.ビューのテスト
5B-1.サーバの起動:
変更を加えた後、以下のコマンドを使用して開発サーバを再起動します。
$ python manage.py runserver
5B-2.ブラウザでの確認:
ブラウザを開き、http://localhost:8000/polls/にアクセスしてください。"Hello, world. You're at the polls index."と表示されるはずです。
5C.トラブルシューティング
もしページが表示されない場合は、URLを正しく入力しているか(http://localhost:8000/polls/)確認してください。
5D.path()関数について
path()関数: Djangoのルーティングにおいて重要な関数で、4つの引数を受け取ります:route、view、kwargs、name。routeとviewは必須で、kwargsとnameは省略可能です。
route (ルート):
説明: routeはURLパターンを定義する文字列です。DjangoはリクエストされたURLをこのパターンと照合し、一致するものを探します。
挙動: routeはドメイン名(例: https://www.example.com)を含まず、URLのパス部分(例: /myapp/)のみを考慮します。GETやPOSTのパラメーターやドメイン名は検索対象に含まれません。
例: path('polls/', views.index, name='index') は、URLが polls/ で終わるリクエストを views.index ビューにマッピングします。
view (ビュー):
説明: viewはDjangoがリクエストに対して呼び出すビュー関数です。routeで定義されたURLパターンに一致するリクエストがあると、Djangoはこのビュー関数を呼び出します。
挙動: ビュー関数は、HttpRequestオブジェクトを第一引数に取り、routeから取得されたキーワード引数(kwargsがあれば)を追加引数として取ります。
例: views.indexは、indexという名前のビュー関数を参照します。
kwargs (キーワード引数):
説明: kwargsは任意のキーワード引数をビュー関数に渡すためのものです。これを使うと、URLの一部ではない追加データをビューに渡すことができます。
挙動: kwargsで指定された引数は、辞書としてビュー関数に渡されます。
例: path('polls/', views.index, name='index', kwargs={'foo': 'bar'})は、ビュー関数にfooというキーワード引数をbarという値で渡します。
name (名前):
説明: nameはURLパターンに名前を付けるためのものです。名前付きURLを使用すると、テンプレートやビュー内で簡単に参照できます。
挙動: 名前付きURLを使用すると、プロジェクト全体でURLを一箇所で変更することができ、それによって参照されている全てのテンプレートやビューに自動的に反映されます。
例: name='index'は、URLパターンにindexという名前を付けます。これにより、テンプレート内で{% url 'index' %}と記述することで、対応するURLに動的にリンクできるようになります。
これで、最初のビューの作成とURLの設定が完了しました。
6.データベースの設定とマイグレーション
6A.データベースの設定
Djangoプロジェクトでデータベースを設定するには、mysite/settings.pyファイルでデータベースの設定を行います。このファイルはDjangoプロジェクトの構成情報を保持し、データベースの設定もその一部です。
6A-1.SQLiteの利用:
設定方法: DjangoのデフォルトデータベースはSQLiteです。設定はすでにmysite/settings.pyの中のDATABASES設定に書かれています。通常、このデフォルト設定でそのまま使用できます。
設定例:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
SQLiteの特徴: ファイルベースのデータベースで、設定が非常に簡単です。開発やテストには最適ですが、大規模な本番環境には推奨されません。
6A-2.他のデータベースへの切り替え(任意):
設定方法: PostgreSQL, MySQL, Oracleなど他のデータベースを使用する場合、ENGINEを該当するデータベースに設定し、NAME、USER、PASSWORD、HOSTをデータベースに合わせて設定します。そのほかのデータベースを用いる場合、インストールおよびデータベースの準備が必要になります。
設定例 (PostgreSQLの場合):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
注意点: PostgreSQLやMySQLなどのデータベースを使用する場合は、対応するPythonデータベースバインディングをインストールする必要があります。また、データベース自体をセットアップし、ユーザーや権限を適切に設定する必要があります。
DjangoプロジェクトでPostgreSQLを使用するには、psycopg2パッケージが必要です。以下のコマンドでインストールできます:
pip install psycopg2
新しいデータベース設定で、以下のコマンドを実行して、Djangoプロジェクトのデータベースマイグレーションを行います。
python manage.py migrate
6B.タイムゾーンの設定
プロジェクトで使用するタイムゾーンをTIME_ZONE設定で指定します。例えば、日本のタイムゾーンを設定するには以下のようにします。
TIME_ZONE = 'Asia/Tokyo'
6C.LANGUAGE_CODEの設定
LANGUAGE_CODEは、Djangoプロジェクトで使用されるデフォルトの言語を設定するための設定項目です。この設定はDjangoが提供する国際化(i18n)と地域化(l10n)のフレームワークにおいて、翻訳されたテキストの表示や、日付や数字のフォーマットに影響を与えます。
mysite/settings.pyファイルのLANGUAGE_CODEを'ja'に設定すると、Djangoプロジェクトのデフォルトの言語が日本語に設定されます。これは、テンプレートや管理サイトなど、Djangoが提供するテキストが日本語で表示されることを意味します。
# mysite/settings.py
LANGUAGE_CODE = 'ja'
以下のような影響があります:
日本語の表示:
Djangoが提供する標準メッセージ(例:管理サイトの各種メッセージ、フォームのエラーメッセージ)が日本語で表示されます。
日付や時間のフォーマット:
日付や時間の表示が日本の標準に従うようになります。例えば、日付は「年/月/日」の形式で表示されるようになります。
デフォルトの翻訳ファイルの利用:
Djangoには多言語対応のためのデフォルトの翻訳ファイルが用意されており、LANGUAGE_CODEに基づいて適切な翻訳ファイルが選択されます。
アプリケーションの翻訳テキスト:
Djangoの国際化機能を利用して、あなたのアプリケーションのテキストを翻訳する場合、LANGUAGE_CODEで設定された言語が基準となります。
注意点
プロジェクトで多言語をサポートする場合、LANGUAGE_CODEはデフォルトの言語を設定しますが、LANGUAGES設定で利用可能な言語を明示的に定義することができます。
日本語を含む多言語対応を行う場合、USE_I18N = TrueとUSE_L10N = Trueもsettings.pyに設定する必要があります。
LANGUAGE_CODEの設定は、Djangoプロジェクトがグローバルなユーザーベースに対応するための第一歩であり、ユーザーにとって親しみやすいインターフェースを提供するために非常に重要です。
6D.INSTALLED_APPSの確認
INSTALLED_APPS設定には、プロジェクトで有効になっているDjangoアプリケーションがリストされています。これにはDjangoが提供する以下のような組み込みアプリケーションが含まれています。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
以下に、INSTALLED_APPSのデフォルト設定にリストされている主要なDjango組み込みアプリケーションの概要と役割を説明します。
django.contrib.admin:
説明: Djangoの管理サイトです。管理者がユーザー、グループ、権限、およびアプリケーションによって追加された他のモデルを管理できるようにする強力なインターフェースを提供します。
役割: サイト管理者がデータを追加、編集、削除できるようにすることで、サイトのバックエンド管理を容易にします。
django.contrib.auth:
説明: 認証システムです。ユーザー認証のためのフレームワークを提供し、ユーザーのログイン、ログアウト、アカウント管理などを扱います。
役割: セキュアなユーザー認証と権限管理を提供し、ユーザーに基づいたアクセスコントロールを可能にします。
django.contrib.contenttypes:
説明: コンテンツタイプフレームワークです。Djangoで使用されるモデルを追跡し、モデル間で汎用的な関係を作成するために使用されます。
役割: モデル間の汎用的な関係を可能にし、モデルを動的に参照するための基盤を提供します。
django.contrib.sessions:
説明: セッションフレームワークです。サイトの訪問者ごとにセッションデータを格納し、複数のリクエストにわたってユーザーの情報を保持することができます。
役割: ユーザーセッションの管理を通じて、状態情報(例えば、ログイン状態)を複数のページリクエストにわたって保持します。
django.contrib.messages:
説明: メッセージフレームワークです。一時的なメッセージ(通知、警告、エラーメッセージなど)をユーザーに表示する機能を提供します。
役割: ユーザーインタフェースに一時的なメッセージを表示し、アプリケーションとユーザー間の通信を効果的に行います。
django.contrib.staticfiles:
説明: 静的ファイル(CSS, JavaScript, 画像ファイルなど)の管理フレームワークです。静的ファイルをアプリケーションに組み込み、配信するための便利な方法を提供します。
役割: 静的ファイルの組織化と配信を容易にし、Web開発におけるアセット管理を効率化します。
6E.データベーステーブルのマイグレーション
Djangoプロジェクトでデータベースのテーブルを作成するには、python manage.py migrateコマンドを実行します。これにより、INSTALLED_APPSで指定されたアプリケーションに必要なテーブルが自動的に作成されます。
$ python manage.py migrate
マイグレーションを実行すると、DjangoはINSTALLED_APPSにリストされているアプリケーションのマイグレーションファイルを参照し、データベースにテーブルを作成します。
このようにして、Djangoプロジェクトのデータベース設定とマイグレーションを行うことで、アプリケーションのデータ管理と運用が可能になります。
7.モデルの作成と理解
7A.モデルの概念と設計思想の理解
Djangoにおけるモデルは、アプリケーションのデータ構造とビジネスロジックを定義する核心的な部分です。
モデルは、データベースのテーブルに対応し、データを操作するためのメソッドやビジネスロジックを含んでいます。
Djangoの設計思想は「DRY - Don't Repeat Yourself」であり、これは情報を一つの場所に集約し、重複を避けることを意味します。
この原則に従い、Djangoはデータモデルの定義を中心に、データベーススキーマの生成、データの操作、ビューとの連携など、多岐にわたる機能を提供します。
実装例: Pollアプリケーションのモデル
質問(Question)と選択肢(Choice)の2つのモデルを作成する場合について説明します。実装は、7Bで行います。
Questionモデル:
question_text: 質問の内容を表すテキストフィールドです。
pub_date: 質問が公開された日時を表す日時フィールドです。
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
このモデルは、各質問の内容と公開日時を保持します。CharFieldは文字列データを保存し、DateTimeFieldは日時データを保存します。
Choiceモデル:
question: この選択肢が属する質問です。ForeignKeyを使ってQuestionモデルとリレーションシップを構築します。
choice_text: 選択肢の内容を表すテキストフィールドです。
votes: この選択肢が得た投票数です。デフォルト値は0です。
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
ChoiceモデルはForeignKeyを使用してQuestionモデルにリンクされており、これにより質問とその選択肢の間の関係が定義されます。on_delete=models.CASCADEは、関連する質問が削除された場合、その質問の選択肢も同時に削除されることを意味します。
モデルのメリットとDjangoのDRY原則
中央集権的なデータ定義:
モデルを使用することで、データ構造とその挙動をアプリケーションの中央で定義し、この一元的な定義を基にデータベーススキーマを生成し、データ操作を行います。
マイグレーションによるスキーマ管理:
モデルの変更があるたびに、Djangoはこれをマイグレーションファイルとして記録します。これにより、データベーススキーマのバージョン管理が容易になり、開発から本番環境への移行がスムーズになります。
データ操作の抽象化:
Djangoモデルは、SQLを直接書く代わりにPythonコードを使用してデータベースと対話するための高レベルなAPIを提供します。これにより、開発プロセスが簡略化され、バグのリスクが低減します。
Djangoのモデルは、データベースとのインターフェースとして機能し、DRY原則に基づいて設計されています。
これにより、データベース構造の変更がアプリケーションの他の部分に自動的に反映され、開発効率とコードの品質が向上します。
7B.モデルの定義
モデルはdjango.db.models.Modelのサブクラスとして定義され、モデルの各フィールドはクラス変数として表現されます。
各フィールドはFieldクラスのインスタンスとして定義され、フィールドの型に応じて様々な属性を持ちます。
以下に、Pollアプリケーションのために先ほど取り上げたQuestionとChoiceモデルの定義例を示します。
Poll には question と publication date の情報があります。 Choice には選択肢のテキストと vote という2つのフィールドがあります。各 Choice は1つの Question に関連づけられています。
Django では、こうした概念を簡単な Python クラスで表現できます。 polls/models.py ファイルを以下のように編集してください:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
このコードでは、以下の概念が表現されています:
モデルの定義:
QuestionとChoiceは、django.db.models.Modelのサブクラスです。
フィールドの定義:
フィールド(例えばquestion_textやpub_date)は、モデルのクラス変数として定義されます。
各フィールドはFieldクラスのインスタンス(例えばCharField、DateTimeField)です。
CharFieldは文字列のフィールドを表し、max_lengthパラメータで最大長を定義します。
DateTimeFieldは日時のフィールドを表します。
人間可読なフィールド名:
pub_dateフィールドの定義では、人間可読な名前"date published"を指定しています。これはオプションで、指定しない場合はフィールド名がそのまま使用されます。
リレーショナルフィールドの定義:
ForeignKeyを使用して、ChoiceモデルがQuestionモデルにリンクされることを示しています。これにより、多対一の関係が形成されます(各Choiceは一つのQuestionに関連付けられます)。
on_delete=models.CASCADEパラメータは、関連するQuestionが削除された場合、それに関連するChoiceも削除されることを意味します。
デフォルト値の設定:
votesフィールドには、デフォルト値として0が設定されています。これは、新しいChoiceオブジェクトが作成されたときにvotesフィールドが明示的に設定されていない場合、自動的に0に設定されることを意味します。
7C.マイグレーションの役割
Djangoでは、モデルの変更をデータベースに反映するためにマイグレーションを使用します。
マイグレーションは、モデルの変更から自動的に生成され、データベーススキーマの変更履歴を表します。
makemigrationsとmigrateコマンドを使用することで、モデルの変更をデータベーススキーマに適用し、アプリケーションのデータモデルを常に最新の状態に保つことができます。マイグレーションについては、8にて実践します。
これで、PollアプリケーションのQuestionとChoiceモデルが定義され、基本的なリレーショナルデータモデルの概念とDjangoでの表現方法が理解できました。
8.モデルを有効にする
8A.モデルの有効化とマイグレーションの基礎
Djangoでモデルを定義したら、そのモデルをプロジェクトに「インストール」し、Djangoがデータベースとのやり取りをできるようにする必要があります。
以下のステップでモデルを有効にし、データベーススキーマを生成し、マイグレーションを通じてモデルの変更を管理する方法を学びます。
8B.アプリケーションの登録
プロジェクトに新しいモデル(例: QuestionとChoice)を認識させるために、pollsアプリケーションをINSTALLED_APPS設定に追加します。
8B-1.PollsConfigクラスの追加:
polls/apps.pyにあるPollsConfigクラスを
mysite/settings.pyのINSTALLED_APPS設定に追加します。
PollsConfig クラスは、 polls/apps.py にあるので、ドットつなぎのパスは 'polls.apps.PollsConfig' となります。
INSTALLED_APPS = [
"polls.apps.PollsConfig", # この行を追加
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
これにより、Djangoはpollsアプリケーションの存在を認識し、そのモデルをプロジェクト全体で利用できるようになります。
8C. マイグレーションの作成
モデルの変更(この場合は新しいモデルの作成)をマイグレーションファイルとして保存します。
$ python manage.py makemigrations polls
このコマンドは以下のような出力を生成し、新しいマイグレーションファイル0001_initial.pyをpolls/migrationsディレクトリに作成します。
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
makemigrations を実行することで、Djangoにモデルに変更があったこと(この場合、新しいものを作成しました)を伝え、そして変更を マイグレーション の形で保存することができました。
8D. 生成されたSQLの確認(オプション)
makemigrationsは実際にデータベースに変更を適用しませんが、どのようなSQLが実行されるかを確認することができます。
$ python manage.py sqlmigrate polls 0001
このコマンドは、マイグレーションによって実行されるSQLコマンドを表示します。これは特にデータベース管理者にSQLスクリプトを提供する必要がある場合や、DjangoがどのようなSQLを生成するかを確認したい場合に役立ちます。
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"question_text" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL,
"question_id" bigint NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED
);
CREATE INDEX
python manage.py sqlmigrate polls 0001コマンドは、pollsアプリケーションの最初のマイグレーション(0001_initial)によって生成されるSQLを表示します。このSQLはデータベースにマイグレーションを適用する前に、何が実行されるかを確認するのに役立ちます。表示されるSQLスクリプトを解析してみましょう。
このスクリプトでは、以下の操作が行われています:
トランザクションの開始:
BEGIN; ステートメントは、以下の全ての操作を一つのトランザクションとして実行することを示します。
Questionモデルのテーブル作成:
CREATE TABLE "polls_question": polls_questionという名前のテーブルを作成します。
このテーブルには、自動インクリメントの主キーid、最大200文字の文字列フィールドquestion_text、そして日時フィールドpub_dateが含まれます。
Choiceモデルのテーブル作成:
CREATE TABLE "polls_choice": polls_choiceという名前のテーブルを作成します。
このテーブルには、自動インクリメントの主キーid、最大200文字の文字列フィールドchoice_text、整数フィールドvotes、そして外部キーquestion_idが含まれます。
question_idはpolls_questionテーブルのidフィールドを参照しており、QuestionとChoiceモデル間のリレーションシップを表します。
インデックスの作成(具体的なインデックス名やカラムは省略されています):
CREATE INDEX: Djangoは関連フィールドにインデックスを作成し、データベースのクエリパフォーマンスを向上させます。
8E. マイグレーションの適用
最後に、マイグレーションを実際にデータベースに適用し、モデルの変更(新しいテーブルの作成)を反映します。
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
このコマンドは、適用されていないすべてのマイグレーション(この場合はpollsアプリケーションの0001_initialマイグレーション)をデータベースに適用します。
8F.設計思想: Djangoアプリケーションのプラガブル性
Djangoアプリケーションは「プラガブル(pluggable)」と設計されており、特定のDjangoインストールに固定されず、容易に再利用や配布が可能です。INSTALLED_APPSにアプリケーションを追加することで、そのアプリケーションのモデルをプロジェクトで使用できるようになり、Djangoはマイグレーションを通じてアプリケーションのデータモデルの変更をデータベーススキーマに反映します。
マイグレーションシステムは、モデルの変更を継続的に追跡し、データベーススキーマを更新する強力なメカニズムを提供します。これにより、開発プロセスが柔軟かつ効率的になり、データベースのスキーマ変更を安全かつ一貫性を持って行うことができます。
9.DjangoシェルでのAPI操作
Djangoの強力なデータベースAPIを使用して、モデルを操作する方法について解説します。
Djangoシェルを通じて、モデルの作成、読み取り、更新、削除(CRUD操作)を行い、Djangoが提供するオブジェクトリレーションシップの利便性を体験します。
9A.Djangoシェルの起動
Djangoプロジェクトのルートディレクトリで以下のコマンドを実行して、Djangoシェルを起動します。
$ python manage.py shell
このコマンドはmanage.pyスクリプトを通じてDjango環境をセットアップし、Python対話シェルを起動します。
9B.モデルのインポートと基本操作
最初にpollsアプリケーションからQuestionとChoiceモデルをインポートします。
>>> from polls.models import Choice, Question
新しい質問の作成
新しいQuestionインスタンスを作成し、データベースに保存します。
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
>>> q.save()
作成したQuestionインスタンスの属性にアクセスします。
>>> q.id
1
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2023, 1, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
質問のテキストを変更し、変更を保存します。
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
<Question: Question object (1)> は、このオブジェクトの表現としてまったく役に立ちません。(polls/models.py ファイル内にある) Question モデルを編集してこれを修正しましょう。 __str__() メソッドを Question と Choice の両方に追加します。
DjangoのデータベースAPIを使用する際、モデルのインスタンスがシェルやDjango管理サイトでどのように表示されるかは、モデルの__str__()メソッドによって大きく影響を受けます。
デフォルトでは、モデルのインスタンスは<Question: Question object (1)>のように表示されますが、これは非常に情報が少ないため、実際のオブジェクトを識別するのに役立ちません。
__str__()メソッドの追加
polls/models.pyに__str__()メソッドをQuestionクラスとChoiceクラスに追加します。これにより、オブジェクトの文字列表現が改善されます。
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
__str__()メソッドはPythonの標準メソッドで、オブジェクトの文字列表現を定義します。Djangoでは、このメソッドの値が管理サイトやシェルでオブジェクトを表示する際に使用されます。
モデルクラスにカスタムメソッドを追加する
Djangoのモデルクラスには、カスタムメソッドを追加することができます。これにより、モデルに特定の振る舞いを実装することが可能になります。
カスタムメソッドの例: was_published_recently
先ほどの、Questionモデルに、質問が最近公開されたかどうかを判定するメソッドwas_published_recently()を追加します。
import datetime
from django.utils import timezone
from django.db import models
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
データベースクエリの実行
作成した質問の一覧を取得し、フィルタリングやソートなどのクエリを実行します。
この記事が気に入ったらサポートをしてみませんか?