Skip to main content

django manage SPA

アプリを作成する

djangoのstartappの代わりに、create-react-appでアプリを作成します。 nodeをインストール後、npm install -g create-react-appを実行することで使用できます。

  • django-admin startproject my-project
  • cd my-project
  • create-react-app my-react-app
  • cd my-react-app

ルーティングの設定

urls.pyを次のように設定させます

from django.conf import settings
...
url_patterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

submodules = ["my-react-app"]

for name in submodules:
route = name if name != "core" else ""
temp = 'static/%s/index.html' % name
view = TemplateView.as_view(template_name=temp)
urlpatterns += [re_path(route, view, name=name)]

staticのディレクトリを設定する

ビルド結果のフォルダを次のようにsettings.pyで指定させます。

submodules = ["my-react-app"]
STATICFILES_DIRS = []
for s in submodules:
STATICFILES_DIRS += [
os.path.join(BASE_DIR, "%s/build/%s/static" % (s, s)),
os.path.join(BASE_DIR, "%s/build" % (s))
]

ここで二重に設定させたのは、複数のReactアプリが存在する場合、 static内のファイルを同じ場所で管理できるようにするためです。 このとき、staticディレクトリが重複してしまうため、 ignoreを指定してファイルを集める必要があります。

CRAのbuild先を上書きする

npm install -D react-app-rewiredを実行後、config-overrides.jsを次のようにします

const fs = require('fs');
const path = require('path');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

module.exports = {
paths: (paths, env) => {
const basename = path.basename(__dirname)
paths.appBuild = resolveApp(`build/${basename}`);
return paths;
}
}
  • npx react-app-rewired build
  • python manage.py collectstatic --ignore=static/

Rest APIを作る

先ほど作成したmy-react-appでAPIを使用します。 python manage.py startapp my-react-appを実行すると、 ディレクトリ内にPythonファイルが作成されます。 settings.pyを編集します。

INSTALLED_APPS += ['my-react-app']

my-project/urls.pyに次のように追加します

from django.conf import settings
# ...
url_patterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

submodules = ["my-react-app"]

for name in submodules:
route = name if name != "core" else ""
temp = 'static/%s/index.html' % name
view = TemplateView.as_view(template_name=temp)
urlpatterns += [re_path(route, view, name=name)]

開発用にサーバーを立てるコマンドを作成する

DjangoとNode.jsのサーバーを同時に用意する際のコマンドを用意しておきます。

my-react-app/management
│ __init__.py

└─commands
│ npm_start_runserver.py
└─ __init__.py

npm_start_runserver.pyを次のように編集します。

import sys
import subprocess
from django.core.management.base import BaseCommand

class Command(BaseCommand):
help = "npm start and runserver"

def handle(self, *args, **options):
proc = subprocess.Popen(["npm", "start"], shell=True, cwd='./note')
cmds = [sys.executable, sys.argv[0], 'runserver', '0.0.0.0:8000']
subprocess.run(cmds, shell=True, cwd=".")
proc.close()

python manage.py npm_start_runserver で立ち上げることができます。