初めに
初投稿です。
最近Web系の開発に興味があり、色々勉強しています。
この記事では、バックエンドの部分をDjangoで、
フロントエンドの部分をNuxt.jsで作成したものについて、
とりあえず開発環境で動くもので書いていきます。
準備
下記イメージを元にdocker-composeを使ってそれぞれの環境を構築
###環境
Window10 Pro
Docker desktop v2.1.0.5
Python 3.6.9
django 2.2.7
djangorestframework 3.10.3
MySQL Ver 8.0.17
Nuxt.js v2.11.0
###ディレクトリ構造
.
├─django
│ ├─manage.py
│ ├─composeexample
│ │ ├─settings.py
│ │ ├─urls.py
│ │ ├─wsgi.py
│ │ └─__init__.py
│ └─myapp
│ ├─migrations
│ ├─admin.py
│ ├─apps.py
│ ├─models.py
│ ├─renderers.py
│ ├─serializers.py
│ ├─tests.py
│ ├─urls.py
│ ├─views.py
│ └─__init__.py
│
├─docker-compose.yml
│
├─dockerfiles
│ ├─django_docker
│ │ ├─dockerfile
│ │ └─requirements.txt
│ └─nuxt_docker
│ └─dockerfile
│
├─mysql
│ └─conf.d
│
└─nuxt
└─front
└─以下略
###各種ファイル
version: '3'
services:
db:
image: mysql:latest
restart: always
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: test
MYSQL_USER: test
MYSQL_DATABASE: test
MYSQL_PASSWORD: test
ports:
- 3306:3306
expose:
- 3306
volumes:
- mysqldata:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
web:
container_name: django
build: ./dockerfiles/django_docker
command:
python3 manage.py runserver 0.0.0.0:8000
volumes:
- ./django:/code
ports:
- "8000:8000"
depends_on:
- db
front:
container_name: nuxt
build: ./dockerfiles/nuxt_docker
tty: true
volumes:
- ./nuxt:/code
ports:
- "3000:3000"
volumes:
mysqldata:
# ベースイメージを指定
FROM python:3.6-stretch
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
# ディレクトリを移動する
WORKDIR /code
# pipでrequirements.txtに記載のパッケージをインストール
COPY requirements.txt /code/
RUN pip3 install -r requirements.txt
COPY . /code/
※djangoのイメージはOpen SSHの鍵長の関係でstretchでbuildしてます。こちら参照
Django>=2.0,<3.0
djangorestframework
django-webpack-loader
django-cors-headers
mysqlclient
※requierment.txtに必要となるpythonのパッケージを記載します。
Djangoだけでなく、今回APIに必要なパッケージも入れます。
以下はDjango REST frameworkに必要なもの
__ ・djangorestframework__
__ ・django-webpack-loader__
__ ・django-cors-headers__
また以下はMySQLをDjangoから使うのに必要なもの
__ ・mysqlclient__
# ベースイメージを指定
FROM node:latest
RUN mkdir -p /code
# node.js の環境変数を定義する
# 本番環境では production
ENV NODE_ENV=development
# yarnとaxiosをinstall
RUN yarn install
RUN yarn add @nuxtjs/axios
# ディレクトリを移動する
WORKDIR /code
# ポート3000番を開放する
EXPOSE 3000
#djangoの構築
###プロジェクトの作成
こちらの記事を参考にしてます。
Djangoを最速でマスターする part1
DockerでDjangoの開発環境を作成する(Quickstart: Compose and DjangoのMySQL版)
【Django】アプリケーションの追加手順
まずdocker-composeでコンテナを立ち上げます。MySQLから建てます。
> docker-compose up -d db
docker ps で確認
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
285cf6b8473b mysql:latest "docker-entrypoint.s…" 2 minutes ago Up 4 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
続いてdocker-composeでコンテナを立ち上げます。初回なのでbuildもしておきます。
> docker-compose up -d --build
Djangoのプロジェクトを作ります。(プロジェクト名は任意です)
> docker-compose run web django-admin.py startproject composeexample .
この部分が生成されます。
.
└─django
├─manage.py
└─composeexample
├─settings.py
├─urls.py
├─wsgi.py
└─__init__.py
続いてsetting.pyを編集します。
デフォルトではSQLiteを使用するようになっているので、これをMySQLに変更します。
#<変更前>
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
#上記を↓↓↓に変更
#ユーザ名やパスは適宜変更してください
#<変更後>
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'test',
'PASSWORD': 'test',
'HOST': 'db',
'PORT': '3306',
}
}
次は連携したDBのマイグレーションを行います。
> docker-compose run web ./manage.py migrate
スーパユーザを作成します。
> docker-compose run web ./manage.py createsuperuser --username admin --email admin@localhost
Starting mysql ... done
Password: #パスワードを聞かれるので入力
Password (again): #再度入力
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common. #パスワードが短いと警告が出る
Bypass password validation and create user anyway? [y/N]: y #yを入力
Superuser created successfully.
ここで一度djangoの開発用サーバを起動してみます。
docker-compose up -dでdocker-compose.ymlに記載したコンテナが全てバックグラウンドで起動します。
(Nuxtのコンテナもこの段階で起動しています)
> docker-compose up -d
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
746b29edf07b working_web "python3 manage.py r…" 30 hours ago Up 30 hours 0.0.0.0:8000->8000/tcp django
0ae9f6506532 mysql:latest "docker-entrypoint.s…" 30 hours ago Up 30 hours 3306/tcp, 33060/tcp, 0.0.0.0:3306->3306/tcp mysql
0107b2a7301b working_front "docker-entrypoint.s…" 30 hours ago Up 30 hours 0.0.0.0:3000->3000/tcp nuxt
django開発用サーバはポート8000で待ち受けているので、
http://localhost:8000/admin にアクセスしてみます。
./docker-compose.ymlの下記に該当します。
#~略~
command:
python3 manage.py runserver 0.0.0.0:8000
#~略~
下記画面が出れば成功です。(Chromeの拡張入れているので背景が黒いです)
作成したスーパユーザでログインしてみます。
デフォルトでは2つのユーザが作られていることがわかります。
###アプリの作成
続いてアプリ部分を生成します。(アプリ名は任意です)
> docker-compose run web ./manage.py startapp myapp
この部分が生成されます。
.
└─django
└─myapp
├─migrations
├─admin.py
├─apps.py
├─model.py
├─tests.py
├─view.py
└─__init__.py
setting.pyに作成したアプリを追記します。
これをしないとdjango上で生成したアプリが認識されません。
# ~略~
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', #追加
]
# ~略~
生成されたmodels.pyにモデルを追記していきます。
とりあえず簡易なPerson_dataモデルを作成します。
人の名前と年齢のみを保持したものです。
ここに記載し、マイグレーションをすることでMySQL上にテーブルが作成されます。
from django.db import models
# Create your models here.
class Person_data(models.Model):
person_name = models.TextField()
person_age = models.IntegerField()
下記でマイグレーションを行います。
アプリを追加した場合はmakemigrationsが必要です。
> docker-compose run web ./manage.py makemigrations
> docker-compose run web ./manage.py migrate
admin.pyに下記を追記することで、管理画面から作成したモデルを確認できます。
from django.contrib import admin
from .models import Person_data #作成したモデルをimport
# Register your models here.
admin.site.register(Person_data) #作成したモデルを追記
+ADDをクリックするとデータ追加画面が開きます。
SAVEで追加できます。
適当にデータを追加していくと下記のように行が増えていきます。
下記でMySQL上でも確認できます。
> docker exec -it mysql /bin/bash #MySQLコンテナに入る
> mysql -u test -p #MySQL起動
Enter password: #本記事の例だとtestでログイン可能
> use test;
> select * from myapp_person_data;
+----+-------------+------------+
| id | person_name | person_age |
+----+-------------+------------+
| 1 | takashi | 26 |
| 2 | naoto | 32 |
| 3 | tomoko | 15 |
+----+-------------+------------+
3 rows in set (0.00 sec)
ここまででdjangoの準備は完了です。
#Django REST frameworkの構築
Djangoの準備ができたところで、次はDjango側にAPIを作っていきます。
GETで上記テーブルの中身を取得するだけの簡易なものを作成します。
まずはsetting.pyに追記していきます。
ここはこちらを参考にしています。
Django REST frameworkでAPIを作ってみた
Django REST Framework で API サーバーを実装して得た知見まとめ(OAuthもあるよ)
# ~略~
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
'rest_framework', #追加
]
# ~略~
__'rest_framework'__を追記することで、Django REST frameworkの機能を使用できるようになります。
続いて、Serializer.pyとRenderer.pyとurls.py(myapp配下)を手動で新規作成し、下記内容を追記します。
.
└─django
└─myapp
├─migrations
├─admin.py
├─apps.py
├─model.py
├─tests.py
├─view.py
├─renderers.py #これ
├─serializers.py #これ
├─urls.py #これ
└─__init__.py
from rest_framework import serializers
from .models import Person_data
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person_data
fields = '__all__'
import json
from rest_framework.renderers import JSONRenderer
class PersonJSONRenderer(JSONRenderer):
charset = 'utf-8'
def render(self, data, accepted_media_type=None, renderer_context=None):
return json.dumps({'person_data': data},ensure_ascii=False)
from django.urls import path
from .views import PersonListApiView
urlpatterns = [
path('get_person/', PersonListApiView.as_view()),
]
composeexample配下のurls.pyを編集し、myapp配下のurls.pyを有効にします。
"""composeexample URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include # includeを追加
from myapp import urls # myapp配下のurls.pyをimport
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(urls), # 追加
]
view.pyを編集します。
from django.shortcuts import render
from django.views.generic import ListView
from myapp.models import Person_data
from rest_framework import status
from rest_framework.generics import ListAPIView
from rest_framework.permissions import AllowAny
from .renderers import PersonJSONRenderer
from .serializers import PersonSerializer
# Create your views here.
class PersonListApiView(ListAPIView):
model = Person_data # モデルを指定
queryset = Person_data.objects.all()
permission_classes = (AllowAny, )
renderer_classes = (PersonJSONRenderer, ) # Rendererを指定
serializer_class = PersonSerializer # Serializerを指定
settings.pyに下記を追記します。
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
http://localhost:8000/api/get_person/ を叩いてみます。
結果をjsonで取得てきていれば成功です。
#Nuxt.jsからAPIの結果を取得する
django側のAPIができたので、フロント側を作成していきます。
こちら参考にしてます。
Nuxt.js・Vue.js の基本的な使い方を理解する
Nuxt.js公式サイト
まずnuxt.jsのコンテナに入り、プロジェクトを作成します(プロジェクト名は任意です)。
yarn create nuxt-app frontを入力後の選択肢は基本全てデフォルト値を入れていますが、
rendering modeだけSingle Page Appを指定しました。
ここでの設定はあとでnuxt.config.jsというファイルから変更可能です。
> docker exec -it nuxt /bin/bash
> yarn create nuxt-app front
? Project name front
? Project description My doozie Nuxt.js project
? Author name
? Choose the package manager Yarn
? Choose UI framework None
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose test framework None
? Choose rendering mode Single Page App
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
下記は表示されれば完了です。
🎉 Successfully created project front
To get started:
cd front
yarn dev
To build & start for production:
cd front
yarn build
yarn start
Done in 167.32s.
確認のために開発用サーバを動かす前に、nuxt.config.jsに追記します。
docker上でnuxt.jsを動かす際は下記が必要です。
こちら参考
export default {
mode: 'spa',
//ここから
server: {
port: 3000,
host: '0.0.0.0',
},
//ここまでを追記
/*
** Headers of the page
*/
開発用サーバを動かしてみます。
完了後のメッセージにも記載されていますが、コンテナ内で作成したプロジェクトのフォルダに移動して、
yarn devです。
> cd front
> yarn dev
http://localhost:3000/ にアクセスしてみます。
下記表示であれば成功です。
ここから編集していく際にホットリロードを有効にします。
docker上で開発するためには明示的に指定が必要です。
こちら参考
下記をファイル末尾に追記します。
export default {
//~略~
}, //追記の際はこのカンマを忘れずに
watchers: {
webpack: {
poll: true
}
}
}
続いてaxiosの設定を追記していきます。
axiosはnode.jsで動くHTTPクライアントで、これを利用してnuxt.jsから先ほどのAPIのURLを叩きます。
前述のnuxtのdockerfileに記載してあるので、すでにコンテナにはインストール済です。
modulesに下記を追記、及びaxiosを追加します。
axios
export default {
//~略~
modules: [
'@nuxtjs/axios',
],
axios: {
baseURL: "http://localhost:8000"
},
//~略~
次に実際のページの編集をしていきます。
今回は簡便にするために、indexを編集していきます。
<template>
<div class="container">
<div>
<logo />
<h1 class="title">
front
</h1>
<h2 class="subtitle">
My doozie Nuxt.js project
</h2>
<div class="links">
<a
href="https://nuxtjs.org/"
target="_blank"
class="button--green"
>
Documentation
</a>
<a
href="https://github.com/nuxt/nuxt.js"
target="_blank"
class="button--grey"
>
GitHub
</a>
<!-- ここから追記 -->
<div v-for="d in dat.person_data" :key=d.person_name align="center">
<h2>
{{d.person_name}} {{d.person_age}}
</h2>
</div>
<!-- ここまで追記 -->
</div>
</div>
</div>
</template>
<script>
import Logo from '~/components/Logo.vue'
export default {
components: {
Logo
},
//ここから追記
data() {
return {
dat: []
}
},
async mounted(){
const url = "/api/get_person/"
const response = await this.$axios.get(url)
this.dat = response.data
}
//ここまで追記
}
</script>
//~略~
このままではCORSにひっかかるので、django側の設定をいじります。
setting.pyに追記します。
# ~略~
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
'rest_framework',
'corsheaders', #追加
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 追加
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ~略~
### 末尾に下記を追加
# 許可するオリジン
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000',
]
# レスポンスを公開する
CORS_ALLOW_CREDENTIALS = True
下記のようにAPI経由で先ほどテーブルに入れたデータが取得できています。
#おわりに
以上でAPI経由でのdjangoとNuxt.jsの簡単な連携ができました。
上記は開発環境のものなので、本番用にまたチューニングする必要があるかと思いますが、
勉強のため一度この段階で投稿させていただきました。