django-best-practices について
Django アプリケーションを開発・レビューする開発者向けのスキルです。28 のトピックを扱い、正誤のコード例と参照資料を通じて、ORM からデプロイまでの指針を示します。
主な機能
- 0128 の Django トピックを網羅
- 02正誤のコード例
- 03ORM クエリと性能の実践指針
- 04セキュリティ、テスト、デプロイの指針
活用シーン
- 01Django のモデル、ビュー、マイグレーションのレビュー
- 02ORM クエリの最適化と N+1 問題への対処
- 03アプリのセキュリティとデプロイ設定の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ ahmetcdincer/ django-skills --skill django-best-practicesインストール後、Claude Code で/django-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/admin.mdarchitecture.mdasync.mdauth.mdcaching.mdcelery.mdchannels.mdcore.mddeployment.mddrf.mdecosystem.mdemail.mdforms.mdi18n.mdlogging.mdmessages.mdmiddleware.mdmigrations.mdmodels.mdpagination.mdqueries.mdsecurity.mdsignals.mdstatic-media.mdtemplates.mdtesting.mdurls.mdviews.md詳細
Django のベストプラクティス
Django 6.0 までを対象とした、ORM クエリからデプロイまで、28 のトピックを網羅するシニア Django 開発者のナレッジベースです。このスキルでは、本番環境向けの高品質な Django アプリケーションを構築するための、誤ったコードと正しいコードの例、およびアーキテクチャに関するガイダンスを提供します。
このスキルを使用する場面
- Django のモデル、フィールド、リレーションを作成または変更するとき
- ビュー(FBV、CBV、DRF ViewSet)を作成するとき
- DRF のシリアライザーや API エンドポイントを作成または更新するとき
- ORM クエリを記述したり、N+1 問題を解決したり、パフォーマンスを最適化したりするとき
- マイグレーションを作成またはレビューするとき
- Django の設定、ミドルウェア、URL ルーティングを構成するとき
- 認証、権限、セッション管理を実装するとき
- キャッシュ(Redis、Memcached、ビュー単位、フラグメント)を設定するとき
- テスト(Django TestCase、pytest、ファクトリー)を記述またはレビューするとき
- Django のシグナル、フォーム、テンプレート、テンプレートタグを扱うとき
- 静的ファイル/メディアファイル、ファイルアップロード、ストレージバックエンドを構成するとき
- バックグラウンドジョブ(Celery または Django 6.0 のネイティブな django.tasks)を設定するとき
- Django をデプロイするとき(Gunicorn、Nginx、Docker、CI/CD)
- Django Channels や WebSocket を扱うとき
- 非同期ビューを作成したり、非同期 ORM を使用したりするとき
- i18n/l10n やタイムゾーン対応を実装するとき
- セキュリティ上の問題(CSRF、XSS、SQL インジェクション、CSP)についてコードをレビューするとき
- クエリセットのページネーション、メール送信、ログ設定、フラッシュメッセージに取り組むとき
- アプリのアーキテクチャ、サービスレイヤー、プロジェクト構成を設計するとき
ワークフロー
このスキルが有効になったら、次の手順に従います。
- トピックを特定する — タスクが Django のどの領域(モデル、ビュー、クエリなど)に関係するかを判断します
- 関連するリファレンスファイルを読む — 以下のリファレンステーブルを参照し、コードを書く前に適切なファイルを読みます
- 正しいパターンを適用する — リファレンスファイルの「Correct」パターンに従い、「Wrong」のアンチパターンを避けます
- よくある間違いを確認する — 各パターンの理由を理解するため、「Why」の説明を確認します
- 関連トピックを相互参照する — タスクが複数の領域(例:ビュー+クエリ+テンプレート)にまたがる場合は、関連するすべてのリファレンスファイルを読みます
そのトピックのコードを書く前に、必ず関連するリファレンスファイルを読んでください。
主な原則
プロジェクト構成
- 設定とアプリを分離します。
config/settings/に base、local、production のファイルを用意します。 - アプリは小さく、目的を絞って構成します(アプリごとにモデルを 3~8 個)。モデルが 15 個を超えたら、アプリを分割します。
- 最初のマイグレーションを行う前に、必ず
AUTH_USER_MODELを設定します。 - ユーザーを参照するときは
auth.Userを直接使わず、settings.AUTH_USER_MODELを使用します。
モデルと ORM
- 金額には
DecimalField、フラグにはBooleanField、メールアドレスにはEmailFieldを使用します。 CharField/TextFieldにnull=Trueを指定してはいけません。省略可能な文字列にはblank=Trueのみを使用します。- 列挙型のフィールドには
TextChoices/IntegerChoicesを使用し、マジック文字列は使いません。 - ForeignKey と OneToOneField には、必ず明示的に
related_nameを設定します。 - ForeignKey/OneToOne には
select_related、ManyToMany/逆 FK にはprefetch_relatedを使用します。 - 競合状態を避けるため、アトミックな更新には
F()式を使用します。 - 存在確認には
.count() > 0ではなくExists()を使用します。 - 一括操作には
bulk_createとbulk_updateを使用します。 - 複数ステップの書き込みは
transaction.atomic()で囲みます。
クエリ
- データベースで処理できる場合、Python でフィルタリングしてはいけません。
- OR/NOT クエリには
Qオブジェクトを使用します。 - N+1 ループの代わりに、
Subqueryとともにannotateを使用します。 - 生 SQL には必ずパラメーターを使用し、f-string は使いません。
- モデルインスタンス全体が不要な場合は
.values_list()を使用します。 .count() > 0ではなく.exists()を使用します。- 大きなクエリセットには
.iterator()を使用します。
ビュー
- 単純な単発ビューには FBV、汎用機能を使った CRUD には CBV を使用します。
- 保護されたビューには、必ず
LoginRequiredMixinまたは@login_requiredを使用します。 - UpdateView/DeleteView で所有権を強制するには、
get_queryset()をオーバーライドします。 - ビューでは
get_object_or_404を使用し、オブジェクトがなくても想定内の場合は.first()を使用します。
フォームとバリデーション
- ModelForm では常に明示的に
fieldsを指定し、excludeや__all__は使用しないでください。 - 単一フィールドのバリデーションには
clean_<field>()を、複数フィールドにまたがるバリデーションにはclean()を使用してください。 - Django 組み込みのバリデーターを使用し、ドメイン固有のルールにはカスタムバリデーターを作成してください。
セキュリティ
- 独自の認証機能を備えた外部 Webhook を除き、CSRF を無効にしないでください。
- ユーザー入力に対して
mark_safe()や|safeを使用しないでください。format_html()を使用してください。 - 生の SQL で f-string を使用しないでください。必ずパラメーター化してください。
- パスワードのハッシュ化には Argon2 を使用し、フォールバックとして PBKDF2 を使用してください。
- 本番環境では
SECURE_SSL_REDIRECT、SECURE_HSTS_*、および Cookie のセキュリティフラグを設定してください。 - コンテンツセキュリティポリシーを設定してください(
SECURE_CSPは Django 6.0 から組み込みです)。 - 有効期限付きトークンには
django.core.signingを使用し、独自のハッシュ実装は使用しないでください。 - ログインをレート制限し、インターネットに公開するサイトでは管理画面を
/admin/以外のパスに移してください。 - デプロイのたびに
manage.py check --deployを実行してください。
認証
- ビューごとのミックスインよりも、
LoginRequiredMiddleware(Django 5.1 以降)と、オプトアウト用の@login_not_requiredの組み合わせを優先してください。デフォルトで安全になります。
管理画面
list_display、list_filter、search_fieldsを必ず設定してください。- リストビューでの N+1 クエリを防ぐには
list_select_relatedを使用してください。 - 計算値や自動設定される値には
readonly_fieldsを使用してください。 - スタッフが実行できる操作を制限するには、権限メソッドをオーバーライドしてください。
テンプレート
base.htmlと{% block %}タグを使ったテンプレート継承を使用してください。{% url %}と{% static %}を必ず使用し、パスをハードコードしないでください。- for ループでは
{% empty %}を、コストの高い検索には{% with %}を使用してください。 {% autoescape off %}や|safeをユーザーコンテンツに使用しないでください。
マイグレーション
- 小さく、目的を絞ったマイグレーションを、内容が分かる名前で作成してください。
- カスタムマイグレーションやデータマイグレーションには、必ず逆操作を用意してください。
- データマイグレーションでは
apps.get_model()を使用し、モデルを直接インポートしないでください。 - カラム削除は複数の段階に分けてください。NULL を許可する → デプロイする → 削除する、の順に進めます。
- 本番環境でマイグレーションを実行する前に、
--planを使って内容を確認してください。
テスト
- DB を使わないテストには
SimpleTestCaseを、DB を使うテストにはTestCaseを使用してください。 - クラス単位のテストデータには
setUpより高速なsetUpTestDataを使用してください。 - JSON フィクスチャの代わりに factory_boy を使用してください。
- 外部サービス(SMS、決済、API)はモックしてください。
- テストには
@override_settingsと Django のlocmemメールバックエンドを使用してください。 - ビジネスロジックのカバレッジは 80%以上を目指してください。
DRF
- シリアライザーでは常に明示的に
fieldsを指定し、__all__は使用しないでください。 - ネストされたデータには、読み取り用と書き込み用のシリアライザーを分けて使用してください。
- グローバルのデフォルト権限として
IsAuthenticatedを設定してください。 - リストエンドポイントには必ずページネーションを設定してください。
- 宣言的なフィルタリングには
django-filterを使用してください。 select_related/prefetch_relatedを使ってget_queryset()を最適化してください。
シグナル
- シグナルはモジュールレベルではなく、
AppConfig.ready()でインポートしてください。 - 重複した接続を防ぐには
dispatch_uidを使用してください。 - 密結合したロジックでは、シグナルより明示的なメソッド呼び出しを優先してください。
- シグナルは、アプリ間の疎結合な通信にのみ使用してください。
キャッシュ
- 開発環境では
DummyCacheを、本番環境では Redis を使用してください。 - タイムアウトを設定した、名前空間付きのキャッシュキーを使用してください。
cache.clear()は使用せず、対象を絞ってキーを無効化してください。- 適切な範囲で、最も細かい単位でキャッシュしてください。
デプロイ
- 本番環境で
runserverを使用せず、Gunicorn または Uvicorn を使用してください。 - マルチステージの Docker ビルドを使用してください。
- シークレットは環境変数に保存し、コードには含めないでください。
- Gunicorn の HUP シグナルを使った、ダウンタイムのないデプロイを使用してください。
- ヘルスチェック用のエンドポイントを必ず用意してください。
バックグラウンドタスク
- タスクにはモデルインスタンスではなく ID を渡してください。
- 指数バックオフを使ったリトライ処理を必ず実装してください。
- タスクは冪等にし、複数回実行しても安全にしてください。
- Celery アプリを直接インポートする代わりに
@shared_taskを使用してください。 - 単純な処理のオフロードに Celery を追加する前に、Django 6.0 のネイティブな
django.tasksの利用を検討してください。 transaction.on_commit()を使い、トランザクション内からタスクをキューに登録してください。
日々の基本
paginator.get_page()でページネーションを行い、必ず先にorder_by()を呼び出します。リンク内では{% querystring %}を使ってフィルターを保持します。- バックグラウンドタスクから、環境ごとのバックエンドを使ってメールを送信します。必ずプレーンテキスト部分も含めます。
disable_existing_loggers: Falseを指定してLOGGINGを設定し、モジュールレベルでgetLogger(__name__)を使用します。print()は決して使わないでください。- ユーザーへのフィードバックには、post/redirect/get パターンとメッセージフレームワークを使用します。
- ロックファイル(pip-tools/uv)で依存関係のバージョンを固定し、コンパイル済みの出力をコミットします。
参照ファイル
このトピックのコードを書く前に、該当する参照ファイルを読んでください。
| トピック | ファイル | 読むタイミング |
|---|---|---|
| プロジェクト構造と設定 | references/core.md | Django プロジェクトのセットアップ、設定の構成、WSGI/ASGI、管理コマンド |
| モデル設計 | references/models.md | モデル、フィールド、リレーション、Meta オプション、マネージャー、抽象モデル/プロキシモデルの作成や変更 |
| ORM クエリ | references/queries.md | クエリの作成、N+1 の解消、Q/F オブジェクトの使用、集計、サブクエリ、トランザクション |
| マイグレーション | references/migrations.md | マイグレーションの作成、データマイグレーション、スカッシュ、ダウンタイムなしのスキーマ変更 |
| Django Admin | references/admin.md | 管理サイト、インラインモデル、カスタムアクション、フィールドセット、管理サイトのセキュリティ/パフォーマンスの設定 |
| ビュー | references/views.md | FBV または CBV、ジェネリックビュー、ミックスインの作成、FBV と CBV の選択 |
| ページネーション | references/pagination.md | クエリセットのページネーション、フィルターを維持するページリンク、キーベースのページネーション、AsyncPaginator |
| URL ルーティング | references/urls.md | URL、名前空間、パスコンバーター、reverse/reverse_lazy の設定 |
| テンプレート | references/templates.md | テンプレート継承、タグ、フィルター、カスタムテンプレートタグ、コンテキストプロセッサー、セキュリティ |
| フォーム | references/forms.md | Django フォーム、ModelForms、バリデーション、カスタムバリデーター、フォームセット、ファイルアップロードのセキュリティ |
| メッセージ | references/messages.md | フォーム送信後のフラッシュメッセージ、SuccessMessageMixin、メッセージレベルとレンダリング |
| 認証とセッション | references/auth.md | ユーザーモデル、認証バックエンド、ログイン/ログアウト、パスワードリセット、権限、グループ、セッション、Cookie |
| ミドルウェア | references/middleware.md | ミドルウェアの順序、カスタムミドルウェア、例外処理、非同期ミドルウェア |
| 静的ファイルとメディアファイル | references/static-media.md | 静的ファイル/メディアファイルの設定、collectstatic、WhiteNoise、S3/CDN、ファイルアップロード、ストレージバックエンド |
| セキュリティ | references/security.md | CSRF、XSS、SQL インジェクション、クリックジャッキング、パスワードハッシュ化、HTTPS、SECRET_KEY、セキュリティチェック |
| シグナル | references/signals.md | pre/post_save、pre/post_delete、m2m_changed、カスタムシグナル、シグナルを避けるべき場合 |
| キャッシュ | references/caching.md | キャッシュバックエンド、Redis、ビュー単位/フラグメント/低レベルのキャッシュ、無効化戦略 |
| 国際化 | references/i18n.md | 国際化の設定、gettext/gettext_lazy、翻訳タグ、タイムゾーンサポート、ロケール構造 |
| テスト | references/testing.md | TestCase の種類、Client/RequestFactory、フィクスチャ、pytest-django、factory_boy、モック、カバレッジ |
| Django REST Framework | references/drf.md | シリアライザー、ビューセット、ルーター、認証、権限、スロットリング、ページネーション、フィルタリング |
| バックグラウンドタスク | references/celery.md | Celery のセットアップ、Django 6.0 のネイティブタスク(django.tasks)、タスク定義、リトライ、キュー、定期タスク、冪等性 |
| メール送信 | references/email.md | send_mail、HTML メール、環境ごとのバックエンド、一括送信、ヘッダーインジェクション |
| ロギング | references/logging.md | LOGGING 設定、組み込みロガー、本番環境でのエラー可視性、Sentry、ログに記録すべきでない情報 |
| 非同期 Django | references/async.md | 非同期ビュー、非同期 ORM(aget/acreate)、sync_to_async、非同期認証/セッション、非同期処理が有効な場合 |
| デプロイとパフォーマンス | references/deployment.md | Gunicorn、Nginx、Docker、CI/CD、ダウンタイムなしのデプロイ、クエリの最適化、インデックス、非同期ビュー |
| Django Channels | references/channels.md | ASGI のセットアップ、WebSocket コンシューマー、チャネルレイヤー、グループメッセージング、WebSocket 認証、SSE |
| Django エコシステム | references/ecosystem.md | DRF、django-filter、allauth、デバッグツールバー、ストレージ、guardian、import-export、unfold、django-redis、サイトマップ、シンジケーションフィード、リダイレクト |
| アーキテクチャパターン | references/architecture.md | カスタムフィールド、マルチ DB、データベースルーター、Jinja2、ORM 内部構造、MTV、サービスレイヤー、DDD、SOLID |
コメント
Markdown 対応