見出し画像

Django ディレクトリ構成とファイル設定


1. 本日の解説内容

本日はディレクトリの構成について解説していきます。Djangoを勉強し始めると、「ディレクトリ構成どうすればいいかわからない」「views.pyやmodels.pyが煩雑になってきた…」といった悩みがありませんでしたか?
また「ファイル設定をどうしたら良いかわからない…」なんてことありませんでしたか?

これらの悩みに対して、ディレクトリの構成方法やファイルの設定について解説していきますので最後まで読んで頂けると幸いです。

なお以下のポートフォリオをベースにディレクトリ構成を解説していきます。主な機能は、「ブログ機能」、「アカウント機能(登録、ログインetc)」、「Q&A機能」ですので、頭の片隅に入れて頂けると後の話が理解しやすくなるかと思います。

https://plusit-1.com/

https://note.com/saito_pythonista/n/n638e967841be/edit

2. ディレクトリ構成の全体図と概略説明

plusit                        #プロジェクトディレクトリ
├── accounts                  #アプリディレクトリ
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py             
│   ├── migrations  
│   ├── models.py
│   ├── tests.py
│   └── views.py              
├── blogs                     #アプリディレクトリ
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py 
│   ├── migrations  
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── media                     #アップロード画像用ディレクトリ
├── config                    #設定ディレクトリ
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   ├── views.py                
│   └── wsgi.py 
├── QA                        #アプリディレクトリ
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py 
│   ├── migrations  
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── static                    #静的ファイルディレクトリ
│   ├── css
│   ├── images
│   └── js
├── templates                 #htmlファイル用ディレクトリ
│   ├── accounts
│   ├── blogs
│   ├── QA
│   └── base.html
└── manage.py

上手のディレクトリの作り方やファイル設定する上でのポイントについて解説していきます。

なお、プロジェクト全体のディレクトリを「プロジェクトディレクトリ」、
(settings.py)のある設定用のディレクトリ「設定ディレクトリ」、アプリ用のディレクトリを「アプリディレクトリ」として進めていきます。

ディレクトリについては、最初にある程度構成を決めてしまった方がベターです。特にアプリについては、最初から機能毎に分割した方が「チーム開発しやすい」、また「コード管理しやすい(バグ防止)」です。

したがって、ディレクトリ構成は最初に設計するようにしましょう。

作り方の手順は以下です。

◆手順
1. 必要ディレクトリ/ファイルの作成
2.ファイルの設定

2.1 必要ディレクトリ/ファイルの作成

前提として、pythonやdjangoがインストールされている前提で解説します。

◆設定ディレクトリの作成
まずプロジェクト全体のディレクトリ(今回はplusit)を作成し、以下のコマンドを入力して設定ディレクトリconfigを作成してください。

plusit
$ django-admin startproject config .

ここで1点ポイントとしては「config(スペース).」とすることです。「(スペース).」がなければ以下のようなconfigディレクトリが2つできてしまい使い勝手が悪くなるので注意です。configの部分は任意名ですが、設定ディレクトリは基本誰がみてもわかるように「config」にします。

plusit                        
├── config
    └── config     

またconfigディレクトリ内にviews.pyファイルを作成します。目的は、トップページ(index)の処理をするためです。

◆アプリディレクトリの作成

djangoでは全体を設定/統括する設定ディレクトリと機能単位を各アプリディレクトリで管理するのがベストプラクティスになっています。

したがって今回の作成手順も機能単位の内容はアプリティレクトリ内で管理する方針で進めていきます。

以下のコマンドで3つアプリを作成します。

plusit
$ python manage.py startapp accounts
$ python manage.py startapp blogs
$ python manage.py startapp QA

アプリ名は任意ですが、認証機能のアプリは”accounts”にした方がいいです。理由としてはdjangoのlogin_requiredといったデコレーターを使う際、accountsでなければ機能しないといった問題が発生するからです。


◆静的ファイル用ディレクトリstaticの作成
plusitディレクトリ直下にstaticディレクトリを作成します。このディレクトリは画像、js、cssといったファイルを扱いますので以下のように設定します。好みや使いやすさに応じてより細分化してももちろんOKです。

 ├── static                    #静的ファイルディレクトリ
    ├── css
    ├── images
    └── js

◆画像アップロード用ディレクトリmediaの作成
plusitディレクトリ直下にmediaディレクトリを作成します。ここではサイト上でユーザーがアップロードした画像を保存するために使用します。

staticとmediaでの違いで混乱するかもしれませんが、「staticは開発者が使う画像」で、mediaは「ユーザーがアップロードした画像」です。

◆htmlファイル用ディレクトリtemplatesの作成
plusitディレクトリ直下にtemplatesディレクトリを作成します。今回は以下のように設定します。

├── templates                 #htmlファイル用ディレクトリ
    ├── accounts
    ├── blogs
    ├── QA
    └── base.html

◆各アプリディレクトリにファイル追加
各アプリティレクトリにurls.pyとforms.pyを追加します。ただし、ユーザーに画面入力させる機能がなければforms.pyはなくてもOKです。

これでディレクトリの全体については完成です

2.2 ファイルの設定

ファイルを設定し各ディレクトリと繋ぎ込みしていきます。config/urls.pyを以下のように設定していきます。

◆urls.pyの設定

以下のようにconfig/urls.pyに情報を記載します。

config/urls.py

from django.contrib import admin
from django.urls import path, include #追加(アプリ)
from django.conf import settings  #追加(静的ファイル)
from django.conf.urls.static import static  #追加(静的ファイル)
from .views import TopPage  #追加(トップページ)

urlpatterns = [
   path('admin/', admin.site.urls),
   path('', TopPage.as_view(), name='toppage’),        #追加(トップページ)
   path('blog/', include('blogs.urls')),               #追加(アプリ)
   path('accounts/', include('accounts.urls')),        #追加(アプリ)
   path('qa/', include('QA.urls')),                    #追加(アプリ)
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
 + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 
 #追加(静的ファイル)

追加部分について順を追って解説していきます。

まずTopPageの部分はトップページを表示するための処置です。pathの第一引数'の意味は、”http://127.0.0.1:8000/(文字列情報なし)”であればトップページを表示させるという指令です。今回は割愛しますがviewの設定やviewからのimportも必要なのでご注意ください。

次にアプリの説明です。includeでアプリのurls.pyと繋ぎ込みをしてください。include(‘アプリ名.urls’)で繋ぎ込みをします。includeのimportも忘れないようご注意ください。

staticの部分については、記載の通りsettings.pyからの情報を受けていますので、settings.pyを記載してから解説します。

◆settings.pyの設定

settings.pyの設定について解説していきます。

◆INSTALLED_APPSの設定

まずsettings.pyに作成したアプリを認識させる必要があります。以下のコードを追加します。…apps.BlogsConfigといったように大文字にする必要があるのでご注意ください。ちなみにBlogsConfigはapp.pyに記載されているクラス名です。

config/settings.py

INSTALLED_APPS = [
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'blogs.apps.BlogsConfig',          #追加
   'accounts.apps.AccountsConfig',    #追加
   'QA.apps.QaConfig',                #追加   
]

◆templatesの設定

templatesを設定してhtmlファイルを読み込めるようにしていきましょう。

config/settings.py

TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [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', 
           ],
       },
   },
]

‘DIRS’の部分はtemplatesディレクトリの位置を示しており、BASE_DIRとはプロジェクトディレクトリ(plusitディレクトリ)をあらわしています。つまり[BASE_DIR / 'templates’]の意味としてはplusitディレクトリの直下のtemplatesディレクトリを参照するということです。これでtemplatesの設定完了です。

(参考)BASE_DIRとは

BASE_DIRはsettings.pyの以下の部分を受けています。

config/settings.py

BASE_DIR = Path(__file__).resolve().parent.parent

意味としては、settings.pyがある場所からみて親(parent)の親なのでplusit(プロジェクトディレクトリ)になります。(settings.py→config→plusit)

少し応用ですがデプロイをする際以下のようにディレクトリを設定することがあります。

config                        
├── settings
   ├── base.py            #設定のベース
   ├── local.py           #ローカル用
   └── production.py      #デプロイ用

このようにローカルとデプロイでファイル分割する場合は、階層が深くなる分以下のようにparentを調整することがあるのでご注意ください。

settings/base.py

#階層が深くなるのでparentを1つ追加
BASE_DIR = Path(__file__).resolve().parent.parent.parent

◆mediaの設定

静的ファイルを扱っていくための設定をしていきます。

config/settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

#django2の場合以下のように記載
import os
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

先ほどurls.pyに記載した内容とセットで解説していきます。

config/urls.py

urlpatterns = [
                     ︙
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)…

まずstatic(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)にsettings.pyで設定したMEDIA_URLとMEDIA_ROOTを当てはめてみましょう!

当てはめると、static(‘/media/’, BASE_DIR / 'media’)となります。この部分の意味としては、第一引数(‘/media/’)は、どんなurlがきた時djangoに画像を表示させるか指示を出す役割で、第二引数(BASE_DIR / 'media')は、どこから画像を読み取るか場所を表しています。つまり'/media/'というurlがきたらBASE_DIRのmediaディレクトリの画像をdjangoが探すという意味です。

まとめると「urls.pyでは画像表示のための指示出し」をしていて、「settings.pyでは指示の詳細(urlと場所)」を定義しています。

◆staticの解説

config/settings.py

STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = '/var/www/plusit/static'

config/urls.py

urlpatterns = [
                     ︙
]…+static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 

考え方は先ほどと一緒で、urls.pyでは指示出しの記載であり、詳細はsettings.pyで定義します。ただ注意点としてはSTATIC_ROOTというのはデプロイの際に使用するものです。ローカルでのみ開発するならurls.pyの”+static(settings………)”の部分はなくてもいいです。これがmediaとの違いであり、若干ややこしい部分です。

またstatic側にはSTATICFILES_DIRSというものがありこちらが、ローカル環境で画像やcssを読み込むためのディレクトリです。

なぜこのstaticがこのように複雑になっているかというと、STATICFILES_DIRSは以下のように複数選択することも可能で、作るサイトによっては、cssファイルや画像等を分けて管理した方が管理しやすい場合があります。


STATICFILES_DIRS=[BASE_DIR / ‘blogs/static’, \
           BASE_DIR / ‘accounts/static’, \
           BASE_DIR / ‘QA/static’]

ただ複数のstaticファイルがある場合デプロイ環境ではdjangoが処理しにくくなってしまうためSTATICFILES_DIRSの中身を全て
STATIC_ROOTにコピーさせ一極集中
させます。これがSTATICFILES_DIRSとSTATIC_ROOTがそれぞれ存在する理由です。

したがってSTATICFILES_DIRSは複数選択できる設定になっていることからリスト[]を外して記述するとエラーが発生します。またSTATICFILES_DIRSとSTATIC_ROOTを同じ場所に設定するとエラーが発生します。

ここで勘の鋭い方は「ローカル環境ではSTATICFILES_DIRSで画像保管場所を指定するが、urls.py等でdjangoに画像を表示する指示出しをしていない?」と気づくかもしれません。その通りです。画像場所は設定したが読み込むようにdjangoに指示出しをする必要があります。

結論templatesファイルに以下の記述をする必要があります。

{% load static %}

これでcssや画像を反映させることができます。

3. 他のアプリからモジュールをimportしたい場合

アプリを複数に分割するとユーザー機能をブログアプリで使いたいといった場合もあるかと思います。そのような場合は以下のようにしてimportすればOKです。

from アプリ名.モジュール名 import クラス名 or 関数名

ex)
from accounts.models import CustomUser

ディレクトリ構成とファイル設定の解説については以上になります。

4. 今後の記事について

最後に今後投稿する記事について紹介させてください。

次回:会員登録/ログイン等のユーザー機能(無料
次々回:リコメンド機能、検索機能等の高難易機能の実装方法(有料 980円(質問対応あり))※下記「有料記事内容詳細」参考

有料記事では、ポートフォリオで使った難しめな機能全てを解説します。また購入いただいた方には、「クローズドコミュニティに招待し質問OK」にします!!※質問期間は購入から2ヶ月まで

「ググっても見つからない/よくわからない」内容をメインで取り扱っており、コード配布はもちろんしっかり理解を深められるよう「丁寧な解説付き」です。

また質問もOKで、価格980円のため良心的な価格だと思っています。ただし品質担保のため30名限定とします。

「記事を読んでいいと思ってくれた方」「djangoでポートフォリオを作りたい方」、「以下の機能に興味のある方」はぜひご検討お願いします。

◆有料記事内容詳細
・PV(ページビュー)別のランキング、カテゴリー別の記事表示
・検索機能
・wordpressのようなエディタ実装方法
・コンタクトフォーム の設置(メール送信)
・オススメ記事をユーザーに表示するリコメンド機能
・お気に入り登録
・stackoverflowの様なQ&A機能
・login_required等のアクセス制限とアラートの表示

ポートフォリオ参考

5. 関連リンク

筆者twitter
共著者twitter
共著者Note



この記事が気に入ったらサポートをしてみませんか?