LoginSignup
31
30

More than 3 years have passed since last update.

【Django】ディレクトリ構成のプラクティス + 注意点

Posted at

Djangoアプリケーションのディレクトリ

Djangoアプリケーションは1アプリごとにディレクトリを生成するので、
$ python manage.py startapp hogeでアプリを追加していくと、ルートディレクトリにどんどんフォルダが出来てしまう。

ディレクトリごとに機能を分離できるのは良いのだが、すべての機能が並列ではないので、アプリケーションが増えるたびに見通しが悪くなっていってしまう。

自分の場合、./app/sub_app/...とディレクトリをネストし、すっきりさせることが多い。

  • 並列にアプリケーションを作っていく場合の例
    機能は分離できるものの、urlと対応しておらず見通しが悪い。
.
├── account/     (/account/login etc)
├── auth_api/    (/api/auth/...)
├── config
│   └── settings.py
├── email/       (/account/email/...)
├── manage.py
├── password/    (/account/password/...)
└── polls_api/   (/api/polls/...)

  • アプリケーションをネストして作っていく場合の例
    urlとディレクトリが対応し、わかりやすい。
.
├── account/      (/account/login etc)
│   ├── email/    (/account/email/...)
│   └── password/ (/account/password/...)
├── api/
│   ├── auth/     (/api/auth/...)
│   └── polls/    (/api/polls/...)
├── config
│   └── settings.py
└── manage.py

しかし、躓く点が多いので注意点をまとめる。

環境

  • CentOS 7
  • Django 3.0.3
  • Python 3.7.4

前提

以下は、$ django-admin startproject config .とした後、python manage.py startapp accountとした場合のフォルダ構成。

.
├── account
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── config
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── poetry.lock
└── pyproject.toml
  • urls.pyの作成

urls.pyはよくアプリケーションディレクトリに作成するので、account/urls.pyを追加しておく。
TopViewというViewを作成したとする。

account/urls.py
from django.urls import path, include
from . import views

app_name = 'account'
urlpatterns = [
    path("top/", views.TopView.as_view(), name="top")
]

config/urls.pyaccount/urls.pyをincludeしておく。

config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/', include('account.urls')), # 追加
]
  • settings.pyに登録
    最後に、accountアプリケーションをconfig/settings.pyに記入。
config/settings.py
INSTALLED_APPS = [
    # defaults
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # 追加
    'account'
]
  • urlの参照

この場合、TopViewのurlは、/account/topである。
template内では、以下のようにurlを指定する。

<a href="{% url 'account:top'%}">トップぺージへのリンク</a>

HTMLがレンダーされる際、Djangoが以下のように展開してくれる。

<a href="/account/top">トップぺージへのリンク</a>

accountディレクトリ内にアプリケーションを作成

アプリを作成

accountフォルダの中に、パスワード関連機能をまとめたpasswordアプリを作成する。
python manage.py startapp password account/passwordとすると作成されそうなものだが、
残念ながらstartappで位置を指定する場合、ディレクトリを作成してくれない。

$ python manage.py startapp password account/password
CommandError: Destination directory '.../account/password' does not exist, please create it first.

先にディレクトリを作成しろと言われるので、作成。
そうすると、account/password内にアプリが作成される。

$ mkdir account/password
$ python manage.py startapp password account/password

現在のディレクトリ。

.
├── account
│   ├── ()
│   └── password
│        ├── __init__.py
│        ├── admin.py
│        ├── apps.py
│        ├── migrations
│        │   └── __init__.py
│        ├── models.py
│        ├── tests.py
│        └── views.py
├── config
│   └── ()
├── manage.py
├── poetry.lock
└── pyproject.toml

urlを登録

今までと同じように、account/password/urls.pyを作成する。
ViewにPassChangeViewというViewを作成した。

account/password/urls.py
from django.urls import path, include
from . import views

app_name = 'password'
urlpatterns = [
    path('change/', views.PassChangeView.as_view(), name='change'),
]

account/urls.pyurls.pyをincludeする。

この時、password.urlsをincludeすれば動きそうな気がするが、account.password.urlsとしなければ動かないので注意。

account/urls.py
from django.urls import path, include
from . import views

app_name = 'account'
urlpatterns = [
    path("top/", views.TopView.as_view(), name="top"),
    path("password/", include('account.password.urls'), name="password") # 追加
]

このとき、PassChangeViewのurlは/account/password/changeとなる。

urlの参照

template内では、以下のようにurlを指定する。

<a href="{% url 'account:password:change'%}">トップぺージへのリンク</a>

settings.pyにアプリケーションを登録

account/passwordにpasswordが作成されたが、config/settings.pyにアプリケーションを記入しなければマイグレーションができない。
INSTALLED_APPSに記入する際は、:ではなく.を使用する。

config/settings.py
INSTALLED_APPS = [
    # defaults
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'account',
    'account.password' # 追加
]

migrate

passwordアプリケーションのmigrateを行う場合も少し挙動が違うので注意。

$ python manage.py makemigrations password
    -> 〇
$ python manage.py makemigrations account.password
    -> ×
$ python manage.py makemigrations account:password
    -> ×
$ python manage.py makemigrations account/password
    -> ×

まとめ

パスとある程度対応させたディレクトリ構成のほうが把握しやすいのですが、最初はいろんなところで躓いたのでまとめました。
3階層までやるとかなりごちゃごちゃしていくのですが、2階層であればすっきりするのでおすすめです。

31
30
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
30