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
で立ち上げることができます。