Django開発者が犯す間違いトップ10
公開: 2022-03-11このチュートリアルでは、Django開発者がよく犯すいくつかの一般的な間違いと、それらを回避する方法について説明します。 このチュートリアルは、熟練したDjango開発者であっても役立ちます。これは、管理できないほど大きな設定を維持したり、静的アセットで名前の競合が発生したりするなどの間違いは、Djangoに最初に挑戦した新しい開発者だけに限定されないためです。
Djangoは無料のオープンソースPythonWebフレームワークであり、一般的な開発の課題を解決し、柔軟で適切に構造化されたアプリケーションを構築できるようにします。 Djangoには、すぐに使用できる多くの最新機能があります。 個人的には、管理、オブジェクトリレーショナルマッピングツール(ORM)、ルーティング、およびテンプレート機能により、Djangoが最初の選択肢になりました。これは、アプリケーションに多くの作業が必要であり、開発者ができる限り仕事を楽しんでいる間、費やしたいからです。これらの基本的な反復タスクにできるだけ時間をかけないでください。 Djangoを使用すると、柔軟性を損なうことなく、これらすべてを実行できます。
Djangoのキラー機能は、モデルのスキーマと管理パネルモデルから自動的に(自動的に?)構築される強力な構成可能な管理インターフェースであり、ウィザードのように感じさせます。 ユーザーは、管理インターフェースを介して、アクセス制御リスト(ACL)、行レベルのアクセス許可とアクション、フィルター、順序、ウィジェット、フォーム、追加のURLヘルパーなど、想像できるあらゆるものを構成できます。 すべてのアプリケーションには管理パネルが必要だと思います。まだの場合は、基本的なアプリケーションで管理パネルが必要になるのは時間の問題です。 Django adminを使用すると、すばやく柔軟に作成できます。
Djangoには強力なORMがあり、すべての主要なデータベースですぐに使用できます。 怠惰なため、他のORMとは異なり、必要な場合にのみデータベースにアクセスします。 Pythonソースコードから使用できるすべての主要なSQL命令(および関数)をサポートし、Pythonの機能により非常に快適に感じられます。
Djangoのテンプレートエンジンは非常に柔軟性があり、同時に強力です。 多くの標準フィルターとタグを使用できるだけでなく、プロジェクト用の新しいカスタムフィルターとタグを作成することもできます。 Djangoは他のテンプレートエンジンとDjangoテンプレートをサポートし、テンプレート処理用の標準ショートカット関数を介して他のテンプレートエンジンを簡単に統合するためのAPIを提供します。
Djangoには、着信リクエストを解析し、ルータースキーマから新しいURLを構築できるURLルーターなど、他にも多くの大きな機能があります。 全体として、Djangoフレームワークは快適なエクスペリエンスであり、ヘルプが必要なときはいつでもドキュメントを読んでください。
間違いその1:プロジェクトの依存関係にグローバルシステムPython環境を使用する
Pythonのグローバル環境をプロジェクトの依存関係に使用しないでください。依存関係の競合が発生する可能性があります。 Pythonは、複数のパッケージバージョンを同時に使用することはできません。 これは、異なるプロジェクトが同じパッケージの異なる互換性のないバージョンを必要とする場合に問題になる可能性があります。
この間違いは通常、Pythonの環境分離機能について知らない新しいPythonおよびDjango開発者によって引き起こされます。
環境を分離する方法はたくさんありますが、最も一般的な方法は次のとおりです。
- virtualenv: Python環境フォルダーを生成し、環境を[非]アクティブ化し、環境にインストールされているPythonパッケージを管理するためのスクリプトを含むPythonパッケージ。 これは、仕事をする最も簡単な方法であるため、私のお気に入りの方法です。 通常、私はプロジェクトフォルダの近くに環境を作成します。
- virtualenvwrapper:グローバルにインストールされ、作成/削除/アクティブ化などのツールセットを提供するPythonパッケージ。 仮想環境。 すべての仮想環境は1つのフォルダーに保存されます(環境変数WORKON_HOMEを介してオーバーライドできます)。
virtualenvwrapper
の代わりにvirtualenv
を使用することに利点はありません。 - 仮想マシン(VM):アプリケーション専用の仮想マシン全体よりも優れた分離はありません。 VirtualBox(無料)、VMware、Parallels、Proxmox(私の個人的なお気に入りであり、無料バージョンがあります)など、選択できるツールはたくさんあります。 VagrantなどのVM自動化ツールと組み合わせると、これは非常に強力なソリューションになります。
- コンテナー:過去数年間、私はほぼすべてのプロジェクトでDockerを使用してきました。特に、最初から開始するすべての新しいプロジェクトで使用しています。 Dockerは、多くの機能を提供し、コンテナー自動化のためのサードパーティツールを多数備えた素晴らしいツールです。 コンテナの再構築を非常に高速にするレイヤーキャッシュ機能があります。 コンテナーでは、グローバルシステムのPython環境を使用します。これは、すべてのコンテナーに独自のファイルシステムがあり、プロジェクトが高レベルで分離されているためです。 Dockerを使用すると、新しいチームメンバーは、特にDockerの経験がある場合に、プロジェクトの作業をより早く開始できます。
あなたが私に尋ねるなら、私はプロジェクトの依存関係の分離と管理のためにvirtualenv
パッケージとDockerコンテナを好みます。
間違いその2: requirements.txt
ファイルにプロジェクトの依存関係を固定していない
すべての新しいPythonプロジェクトは、requirements.txtファイルと新しい分離環境で開始する必要があります。 通常、すべてのパッケージはpip/easy_install
を介してインストールしますが、 requirements.txt
ファイルにも忘れずに追加してください。 これにより、プロジェクトをサーバーに展開したり、チームメンバーが自分のマシンでプロジェクトをブートストラップしたりするのが簡単になります(より適切になる可能性があります)。
さらに、 requirements.txt
ファイルに依存関係の特定のバージョンを固定することも同様に重要です。 通常、パッケージのバージョンが異なれば、モジュール、関数、および関数パラメーターも異なります。 依存関係のマイナーなバージョン変更でさえ、パッケージを壊す可能性があります。 プロジェクトが稼働中で、定期的に展開をスケジュールしている場合、これは非常に深刻な問題です。バージョン管理を行わないと、ビルドシステムが常に最新バージョンのパッケージをインストールするためです。
常にパッケージを本番用に固定してください! 個人的には、これを行うのに役立つpip-toolsと呼ばれる非常に優れたツールを使用しています。 依存関係の管理に役立つ一連のコマンドラインツールを提供します。 依存関係だけでなく、依存関係の依存関係を含む依存関係ツリー全体を固定するrequirements.txt
が自動的に生成されます。
依存関係リストから一部のパッケージのみを更新したい場合があります(たとえば、Django / Flask /任意のフレームワークまたはユーティリティのみ)。「pipfreeze」を使用した場合、どの依存関係がどのパッケージに対応しているかわからないため、依存関係をアップグレードできません。 ただし、pip-toolsを使用すると、固定した依存関係に応じてパッケージが自動的に固定されるため、更新が必要なパッケージが自動的に解決されます。 ボーナスとして、 requirements.txt
ファイルのコメントでパッケージをマークする方法により、どのパッケージがどの依存関係からのものであるかも正確にわかります。
特に注意するために、依存関係のソースファイルもバックアップすることをお勧めします。 ファイルシステム、Git管理フォルダー、S3フォルダー、FTP、SFTPなど、どこにでもコピーを保存しますが、手元に置いておきます。 リストにない比較的マイナーなパッケージがnpmで多数のパッケージを壊した場合があります。 Pipは、必要なすべての依存関係をソースファイルとしてダウンロードするためのツールを提供します。詳細については、 pip help download
実行してください。
間違いその3:クラスベースのビューの代わりに古いスタイルのPython関数を使用する
特にテストまたはユーティリティビューの場合は、アプリケーションのviews.py
ファイルで小さなPython関数を使用することをお勧めしますが、通常は、アプリケーションでクラスベースビュー(CBV)を使用する必要があります。
CBVは、専門家によって構築され、すべての一般的な動作をカバーする一般的なWeb開発タスクを実装する抽象クラスを提供する汎用ビューです。 これらには驚くべき構造化APIがあり、CBVを使用すると、オブジェクト指向プログラミングのすべての利点を利用できます。 それはあなたのソースコードをより明確で読みやすくします。 リスト、CRUD操作、フォーム処理などにDjango標準ビュー関数を使用する手間を忘れてください。ビューに適したCBVを拡張し、クラスのプロパティまたは関数をオーバーライドするだけです(通常、関数はプロパティを返し、そこに任意のロジックを追加できます)ビューの動作を構成する(CBVの代わりにビュー関数を使用する場合)ソースコードからスパゲッティを作成します。
たとえば、ビューコンテキストの構築、行レベルでの承認の確認、アプリケーション構造からのテンプレートパスの自動構築、スマートキャッシングの統合など、基本的なCBVの動作をオーバーライドするさまざまなミックスインをプロジェクトに含めることができます。
アプリケーション名とビュークラス名に基づいてビューのテンプレート名を標準化するDjangoTemplateNamesという名前のパッケージを作成しました。 私は毎日それを使用し、名前を発明するための私の時間を大幅に節約します。 ミックスインをCBVに入れるだけです— class Detail(TemplateNames, DetailView):
—そしてそれは機能し始めます! もちろん、私の機能を上書きして、モバイルレスポンシブテンプレート、ユーザーエージェント用のさまざまなテンプレート、またはその他の必要なものを追加できます。
間違いその4:ファットビューとスキニーモデルを書く
モデルではなくビューでアプリケーションロジックを記述するということは、モデルに属するコードをビューに記述し、それを「ファット」にし、モデルを「スキニー」にすることを意味します。
ファットモデル、スキニービューを作成する必要があります。
モデルのロジックを小さなメソッドに分割します。 これにより、大量のコードをコピーして貼り付ける代わりに、数行のコードで複数のソース(管理インターフェースUI、フロントエンドUI、APIエンドポイント、複数のビュー)から複数回使用できます。 したがって、次にユーザーに電子メールを送信するときは、コントローラーでこのロジックを記述する代わりに、電子メール関数を使用してモデルを拡張します。
これにより、これが行われるすべてのコントローラーで繰り返しではなく、1つの場所で電子メールロジックをテストできるため、コードの単体テストが容易になります。
この問題の詳細については、Djangoのベストプラクティスプロジェクトをご覧ください。 解決策は簡単です。ファットモデルとスキニービューを作成するので、次のプロジェクトでそれを実行しましょう(または現在のプロジェクトをリファクタリングします)。
間違いその5:巨大で管理しにくい設定ファイル
新しいDjangoプロジェクト設定ファイルでさえ多くの設定があります。 実際のプロジェクトでは、設定ファイルは700行以上の構成になり、特に開発、本番、およびステージング環境のすべてにカスタム構成が必要な場合は、保守が困難になります。
構成ファイルを手動で分割してカスタムローダーを作成することもできますが、私が共同執筆した、十分にテストされたPythonパッケージであるDjangoSplitSettingsを紹介したいと思います。
このパッケージは、パスのワイルドカードをサポートし、同じコンテキストで構成ファイルをインポートする2つの機能( optional
とinclude
)を提供し、以前にロードされたファイルで宣言された構成エントリを使用して構成を簡単に構築できるようにします。 Djangoのパフォーマンスには影響せず、どのプロジェクトでも使用できます。
最小限の構成例を確認してください。
from split_settings.tools import optional, include include( 'components/base.py', 'components/database.py', 'components/*.py', # the project different envs settings optional('envs/devel/*.py'), optional('envs/production/*.py'), optional('envs/staging/*.py'), # for any local settings optional('local_settings.py'), )
間違いその6:オールインワンアプリケーション、不適切なアプリケーション構造、および不適切なリソース配置
Djangoプロジェクトは、複数のアプリケーションで構成されています。 Django表記では、アプリケーションは少なくとも__init__.py
ファイルとmodels.py
ファイルを含むPythonパッケージです。 最新のDjangoバージョンでは、 models.py
は不要になりました。 __init__.py
で十分です。

Djangoアプリケーションには、Pythonモジュール、Django固有のモジュール(ビュー、URL、モデル、管理者、フォーム、テンプレートタグなど)、静的ファイル、テンプレート、データベース移行、管理コマンド、単体テストなどを含めることができます。 モノリスアプリケーションは、単純なロジックを使用して、小さくて再利用可能なアプリケーションに分割する必要があります。 アプリの目的全体を1つか2つの短い文章で説明できるはずです。 例:「ユーザーがメールでアカウントを登録してアクティブ化できるようにします。」
プロジェクトフォルダproject
を呼び出し、アプリケーションをproject/apps/
に配置することをお勧めします。 次に、すべてのアプリケーションの依存関係を独自のサブフォルダーに配置します。
例:
- 静的ファイル:
project/apps/appname/static/appname/
- テンプレートタグ:
project/apps/appname/templatetags/appname.py
- テンプレートファイル:
project/apps/appname/templates/appname/
すべての静的フォルダーが1つのフォルダーにマージされ、2つ以上のアプリケーションにjs/core.js
ファイルがある場合、 settings.INSTALLED_APPLICATIONS
の最後のアプリケーションが前のアプリケーションをオーバーライドするため、常にサブフォルダーのアプリケーション名のプレフィックスを付けます。 私はかつて現在のプロジェクトでこのバグを抱えていましたが、チームがカスタムSPA管理パネルを実装し、同じ方法でファイルに名前を付けたため、別の開発者がstatic/admin/js/core.js
をオーバーライドしたことに気付くまで約6時間のデバッグを失いました。
これは、多くのリソースとPythonモジュールを持つポータルアプリケーションの構造例です。
root@c5b96c395cfb:/test# tree project/apps/portal/ project/apps/portal/ ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ ├── __init__.py │ └── update_portal_feeds.py ├── migrations │ └── __init__.py ├── models.py ├── static │ └── portal │ ├── css │ ├── img │ └── js ├── templates │ └── portal │ └── index.html ├── templatetags │ ├── __init__.py │ └── portal.py ├── tests.py ├── urls.py └── views.py 11 directories, 14 files
このような構造を使用すると、いつでもアプリケーションを別のPythonパッケージにエクスポートして、再度使用できます。 PyPiでオープンソースパッケージとして公開したり、別のフォルダーに移動したりすることもできます。
最終的には、次のようなプロジェクト構造になります。
root@c5b96c395cfb:/test# tree -L 3 . ├── deploy │ ├── chef │ └── docker │ ├── devel │ └── production ├── docs ├── logs ├── manage.py ├── media ├── project │ ├── __init__.py │ ├── apps │ │ ├── auth │ │ ├── blog │ │ ├── faq │ │ ├── pages │ │ ├── portal │ │ └── users │ ├── conf │ ├── settings.py │ ├── static │ ├── templates │ ├── urls.py │ └── wsgi.py └── static └── admin ├── css ├── fonts ├── img └── js 25 directories, 5 files
もちろん、実際のプロジェクトでは、より複雑になりますが、この構造により、物事がよりシンプルでクリーンになります。
間違いその7: STATICFILES_DIRS
とSTATIC_ROOT
は初心者のDjango開発者を混乱させます
静的ファイルは、JavaScript、CSS、画像、フォントなど、アプリの使用によって変更されないアセットです。Djangoでは、デプロイプロセス中にパブリックディレクトリに「収集」されるだけです。
開発モードでは— python manage.py runserver
—DjangoはSTATICFILES_FINDERS
設定を使用して静的ファイルを検索します。 デフォルトでは、 STATICFILES_DIRS
設定にリストされているフォルダーで要求された静的ファイルを見つけようとします。 失敗した場合、Djangoはdjango.contrib.staticfiles.finders.AppDirectoriesFinder
を使用してファイルを検索しようとします。これは、プロジェクトにインストールされているすべてのアプリケーションのstatic
フォルダーを検索します。 これにより、独自の静的ファイルとともに出荷される再利用可能なアプリケーションを作成できます。
本番環境では、NginxなどのスタンドアロンWebサーバーを使用してスタティックを提供します。 Webサーバーは、Djangoプロジェクトのアプリケーション構造や静的ファイルが分散されているフォルダーについて何も知りません。幸い、Djangoは静的管理コマンドpython manage.py collectstatic
collectstaticを提供します。このコマンドは、 STATICFILES_FINDERS
をウォークスルーし、アプリケーションstatic
からすべての静的ファイルをコピーします。フォルダとSTATICFILES_DIRS
にリストされているフォルダを、 STATIC_ROOT
設定で指定したディレクトリに配置します。 これにより、Django開発モードサーバーと同じロジックを使用して静的ファイルリソースを解決でき、すべての静的ファイルをWebサーバーの1か所に配置できます。
本番環境でcollectstatic
を実行することを忘れないでください!
間違いその8:デフォルトSTATICFILES_STORAGE
、本番環境でのDjangoテンプレートローダー
STATICFILES_STORAGE
本番環境の資産管理について話しましょう。 「アセットは期限切れにならない」ポリシーを使用すると、最高のユーザーエクスペリエンスを提供できます(詳細については、こちらをご覧ください)。 つまり、すべての静的ファイルは、数週間、数か月、さらには数年の間、Webブラウザによってキャッシュされる必要があります。 つまり、ユーザーはアセットを1回だけダウンロードする必要があります。
これはすばらしいことです。静的ファイルフォルダーのNginx構成で数行で実行できますが、キャッシュの無効化についてはどうでしょうか。 ユーザーがアセットを1回だけダウンロードする場合、メニュー内のアイテムのロゴ、フォント、JavaScript、またはテキストの色を更新するとどうなりますか? これを回避するには、デプロイごとに静的ファイルの一意のURLとファイル名を生成する必要があります。
ManifestStaticFilesStorageをSTATICFILES_STORAGE
として使用し(ハッシュはDEBUG=false
モードでのみ有効になります)、上記のcollectstatic
管理コマンドを実行するだけで簡単に実行できます。 これにより、本番Webサイトへのアセットリクエスト数が減少し、Webサイトのレンダリングが大幅に高速化されます。
キャッシュされたDjangoテンプレートローダー
もう1つの優れたDjango機能は、キャッシュされたテンプレートローダーです。これは、すべてのテンプレートレンダリングでテンプレートファイルをリロードおよび解析するわけではありません。 テンプレートの解析は非常にコストのかかる操作であり、多くのリソースを使用します。 デフォルトでは、Djangoテンプレートはすべてのリクエストで解析されますが、これは特に、短時間で何千ものリクエストを処理できる本番環境では問題になります。
これを行う方法の良い例と詳細については、 cached.Loader
構成セクションを確認してください。 ローダーはファイルシステムから解析されたテンプレートをリロードしないため、開発モードでは使用しないでください。 テンプレートを変更するたびに、 python manage.py startapp
を使用してプロジェクトを再起動する必要があります。 これは開発中に煩わしい場合がありますが、実稼働環境には最適です。
間違いその9:ユーティリティまたはスクリプト用の純粋なPythonスクリプト
Djangoは、管理コマンドと呼ばれる非常に優れた機能を提供します。 車輪の再発明やプロジェクトユーティリティ用の生のPythonスクリプトを作成する代わりに、これを使用してください。
また、Djangoのカスタム拡張機能のコレクションであるDjangoExtensionsパッケージも確認してください。 たぶん誰かがあなたのコマンドをすでに実装しています! すでに多くの一般的なタスクコマンドがあります。
間違いその10:車輪の再発明
DjangoとPythonには、すぐに使用できる何千ものソリューションがあります。 ユニークではないものを書く前にグーグルを試してみてください。 おそらく、すでに存在する機能豊富なソリューションがあります。
物事を単純にするようにしてください。 グーグルファースト! 高品質のパッケージを見つけたら、プロジェクトにインストール、構成、拡張、統合します。もちろん、機会があればオープンソースに貢献します。
まず、Django用の私自身のパブリックパッケージのリストを次に示します。
- Django Macros URLを使用すると、マクロを使用してDjangoアプリケーションでURLパターンを簡単に記述(および読み取り)できます。
- Django Templates Namesは、CBVテンプレート名を簡単に標準化できる小さなミックスインです。
- django-split-settingsを使用すると、Django設定を複数のファイルとディレクトリに整理できます。 設定を簡単に上書きおよび変更できます。 設定ファイルのパスでワイルドカードを使用し、設定ファイルをオプションとしてマークします。
繰り返さないでください(DRY)!
私はDRY方法論が本当に好きです。 そのため、Djangoスケルトンを便利なツールとして作成しました。このツールには、すぐに使える非常に優れた機能がいくつかあります。
- docker-composeによって管理される開発/本番用のDockerイメージ。これにより、コンテナーのリストを簡単に調整できます。
- 本番環境にデプロイするためのシンプルなファブリックスクリプト。
- ベースソースとローカルソースの設定を含むDjangoSplitSettingsパッケージの構成。
- プロジェクトに統合されたWebpack-
dist
フォルダーのみがcollectstaticコマンドでDjangoによってcollectstatic
されます。 - 本番環境でキャッシュ可能なDjangoテンプレート、ハッシュされた静的ファイル、統合されたデバッグツールバー、ロギングなど、すべての基本的なDjango設定と機能を構成しました。
これは、次のプロジェクトですぐに使用できるDjango Skeletonであり、プロジェクトをブートストラップすることで、多くの時間を節約できることを願っています。 Webpackの基本構成は最小限ですが、 .scss
ファイルを処理するように事前構成されたSASSもインストールされています。