はじめに
皆さんは、何らかのアプリケーションやWebサービスを開発する際にソースコードの管理はどのように行っているでしょうか。
もし何らかのフレームワークを使用しているのであれば、そこで提供されているやり方やファイル構造をそのままにしている人も多いかもしれません。
しかし、コードを管理する際は自分なりにディレクトリ構造を変更するなどした方が良い場合があります。
今回は「このようにファイルを整理した方が良い」という1例をPythonのWebフレームワークであるDjangoを用いて紹介します。
もちろん今回紹介するものだけが最善というわけではありませんが、ファイル構造を考えるきっかけにして頂けると幸いです。
なお、今回はDjangoの具体的な環境構築の話や仕組みについては解説しません。
あくまで、どのようにディレクトリを構成するかに焦点をあてています。
Djangoを始めたい方は環境構築の方法を記事にしているので興味のある方は参考にしてください。
目次
ベストプラクティスとは
今回ではDjangoのベストプラクティスについて考えていきます。
その前にそもそもベストプラクティスとは何でしょうか。
Wikipediaの解説を見てみます。
ベストプラクティス(英: best practice)は、ある結果を得るのに最も効率のよい技法、手法、プロセス、活動などのこと。最善慣行、最良慣行と訳されることもある。また、仕事を行うために最も効率のよい技法、手法などがあるという考え方をいう。
Wikipedia: ベストプラクティス
つまりそこでの最善を求めることがベストプラクティスです。
今回はより分かりやすいディレクトリ構造を模索して、自分や他の人から見ても分かりやすくするにはどうしたらよいかを考えていきます。
ですが、その前に知っておいて欲しいモデルがあります。
MVCモデルとMVTモデル
Web開発で有名なモデルとしてMVCモデルというものがあります。
これらはModel、View、Controllerそれぞれの頭文字です。
引用元: Wikipedia Model View Controller
それぞれの役割は以下のようになっています。
- Model
Modelは、一般的にビジネスロジックと呼ばれる部分になります。
アプリケーションデータやビジネスルール、関数、データベースへのアクセス、データ管理などを担当します。
つまり、そのアプリケーションの機能をつかさどっています。
- View
Viewは、レイアウト部分です。
UIを表示するコンポーネントであり、データ入力フォームやグラフ、図などデザインやレイアウトに関わるアプリケーションのフロントエンドを担当します。
- Controller
Controllerは、ModelとViewの仲介役です。
Viewから受けたデータをModelに渡して、Modelでの処理結果をViewに戻す役割をしています。
つまり、処理を制御している部分になります。
このようにファイルの役割を分けることで、コードとしての構造が分かりやすくなったり、分業して開発を行いやすくなる利点があります。
もちろん現実の開発ではこんなにシンプルに役割分担できないも多いので理想論にはなってしまいますが、それでも意識してこの形を目指していくことは重要です。
ただし、DjangoではMVCモデルではなくMVTモデルを採用しています。
レイアウトを担当するViewがTemplate、それぞれを制御するControllerがViewの役割をしています。
考え方はMVCモデルと同じですが、それぞれの役割が少し異なるという事です。
Djangoでのデフォルトのディレクトリ構造
まずは単純にDjangoでは以下のコマンドでプロジェクトとアプリケーションを立ち上げてみます。
$ django-admin startproject project
また作ったプロジェクト内(この例はapp1)で以下のコマンドを実行します。
$ python manage.py startapp app1
これでプロジェクトとアプリケーションが立ち上がりました。
デフォルトでは以下のようなディレクトリ構造になります。
project/
manage.py
project/
__init__.py
settings.py
urls.py
wsgi.py
app1/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
中身を見て、あれ、MVTモデルなのにtemplateがないじゃん!と思われた方もいるかもしれません。
Djangoはtemplateが提供してくれる訳ではないので、自分で作る必要があります。
cssやimageを入れるstaticフォルダも同様です。
デフォルトではアプリケーションのディレクトリ直下
に作るのでディレクトリ構造は以下のようになります。
project/
manage.py
project/
__init__.py
settings.py
urls.py
wsgi.py
app1/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
templates/ # 追加
hoge.html
tests.py
static/ # 追加
css/
hoge.css
image/
hoge.png
views.py
これでMVTモデルになりました。
それではここからDjangoにおけるベストプラクティスを考えていきます。
Djangoでのベストプラクティスを考える
一見デフォルトでも良さそうなディレクトリの構造ですが、分かりづらくなるような問題を何点か抱えています。
ここで課題解決していきましょう。
問題点1:プロジェクト名と設定ディレクトリ名が同じになっている
wsgi.pyやsettings.pyはそれぞれアプリケーションのデプロイや設定を行うためのファイルです。
これらが入っている設定ディレクトリ名がプロジェクト名と同じだと、どこに何が入っているか分かりづらいです。
通常このような設定ディレクトリはconfigurationからとってconfig(コンフィグ)とするのが一般的です。
ただし、プロジェクトを立ち上げた後にリネームすると他にもいろいろなファイルを変更する必要があります。
そのため、最初からプロジェクトディレクトリを作った後にその中にconfigというプロジェクトを立ち上げてしまった方が楽です。
その時のコマンドは以下のように記述します。
$ mkdir project
$ cd project
$ django-admin startproject config .
$ python manage.py startapp app1
最後の.
は地味ながらも非常に重要です。
これはカレントディレクトリでプロジェクトを立ち上げるという意味になります。
先ほど違いディレクトリの構造が少し分かりやすくなったと思います。
project/
manage.py
config/
__init__.py
settings.py
urls.py
wsgi.py
app1/
__init__.py
...
問題点2:templatesとstaticがアプリケーションごとに存在する
1つのprojectに対して複数のアプリケーションを作ることがあると思います。
そのときにデフォルトの設定だと以下のようにtemplatesがディレクトリごとに存在することになります。
project/
manage.py
config/
__init__.py
...
app1/
__init__.py
...
templates/
hoge.html
static/
css/
hoge.css
image/
hoge.png
app2/
__init__.py
...
templates/
hoge.html
static/
css/
hoge.css
image/
hoge.png
app3/
...
この状態はあまり好ましくありません。
例えばプロジェクト内で同じHTMLファイルから引用して使いまわしたい場合、templatesごとに同じものを用意しなければなりません。
また、この場合app1にあるhoge.htmlとapp2にあるhoge.htmlをDjango側で区別できません。
そのためそれぞれでファイル名を変更する必要があり面倒です。
解決策としてアプリケーションごとだったtemplatesとstaticを1つに統一します。
templatesはprojectディレクトリ直下に置きます。
以下のように変更します。
project/
manage.py
config/
__init__.py
settings.py
...
templates/ # ここを変更
base.html
app1/
hoge.html
app2/
hoge.html
static/ # ここを変更
css/
app1/
hoge.css
app2/
hoge.css
image/
app1/
hoge.png
app2/
hoge.png
app1/
__init__.py
...
app2/
__init__.py
...
templatesの中にapp1やapp2を改めて作っているのは、中にあるhoge.htmlという同じファイル名のファイルを区別するためです。
また、base.htmlはapp1とapp2の両方から引用できるようにtemplates直下に置いています。
このようなディレクトリ構造はこちら側が勝手に行ったことなので、Django側は把握していません。
なのでsettings.pyを変更して教えてあげる必要があります。
以下のように編集します。
# settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #ここを追加
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # ここを追加
DIRSでファイルの場所を指定します。
パスを指定する際に絶対パスではなく、ライブラリを使いBASE_DIR
から位置として相対パスで書いています。
理由があるので少し触れておきます。
例えば、windowsでファイルの場所がC:からは始まることが多いと思いますが、macの場合はhome/で始まります。
絶対パスで書くとパソコンごとに環境の違いに対応できません。
os.path.join(BASE_DIR, 'ファイル名')
としてする事によってどの環境でも同じパスを指定できます。
この記述は大変便利でよく使うので覚えておきましょう。
まとめ
今回はDjangoにおけるベストプラクティスについてを検討しました。
デフォルトではディレクトリが分かりづらい場合は今回のように工夫することも非常に重要です。
ただし、今回説明したやり方だけが正解ではありません。
このあたりの話は開発している人たちの考え方にも依存する部分があります。
いずれにしてもコードを書くだけでなく、ファイルやディレクトリの構成も工夫すると良いでしょう。
皆さんも開発する際には実践してみてください。
CodeShipで実践的な開発手法を学ぶ
CodeShipでは普段の学習カリキュラムや卒業制作を通して、実際の開発現場により近い開発環境の構築やチームを想定した開発手法を学ぶことができます。
卒業要件であるオリジナルポートフォリオの開発は、生徒一人一人がこれまでのカリキュラムで模写などしてこなかった完全オリジナルです。
そのためより効率的に開発するためにはコードだけでなく、ディレクトリの構成も含め開発環境の構築にも工夫に関しても生徒一人一人に合わせて講師がサポートします。