我尝试实现了Nuxt.js前端与Django后端之间的API协作

首先

我是第一次投稿。
最近我对Web开发很感兴趣,正在学习各种知识。
在这篇文章中,我将介绍一个使用Django构建后端部分、使用Nuxt.js构建前端部分的项目,
并将重点放在开发环境中的可用性上。

准备

qiita用1 (2).jpg

环境

Windows10 专业版
Docker 桌面版 v2.1.0.5
Python 3.6.9
Django 2.2.7
Django Rest Framework 3.10.3
MySQL 版本 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的映像是通过stretch构建的,原因是与Open SSH的密钥长度有关。请参考此处。

Django>=2.0,<3.0
djangorestframework
django-webpack-loader
django-cors-headers
mysqlclient

在requierment.txt文件中记录需要的Python包。除了Django,还需要安装与API相关的其他包。

以下是Django REST框架所需的组件:
– djangorestframework
– django-webpack-loader
– django-cors-headers

以下是使用Django连接MySQL所需的必备组件之一: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的第一部分。
通过Docker创建Django的开发环境(快速入门:Compose和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来启动容器。由于这是初次操作,我们也会执行构建操作。

> 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
#~略~
image.png
image.png

创建应用程序

接下来,我们将生成应用程序的部分。(应用程序的名称可以自由选择)

> 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) #作成したモデルを追記
image.png
image.png
image.png

你可以在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框架

在准备好Django之后,接下来我们将在Django中创建API。
我们将创建一个简单的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(在我的应用程序下),并添加以下内容。

.
└─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'
    ]
}
image.png

使用Nuxt.js获取API结果。

已经完成了Django端的API,现在要开始构建前端。
参考了以下内容。
理解Nuxt.js和Vue.js的基本用法。
Nuxt.js官方网站。

首先进入Nuxt.js的容器,创建一个项目(项目名称可以任意)。

在输入 “yarn create nuxt-app front” 之后,选择基本上都采用了默认值,只是将渲染模式设置为单页面应用程序。
这里的设置可以在以后的 “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
image.png

在从这里开始编辑时启用热重载。
如果要在Docker上进行开发,则需要明确指定。
请参考如下所示,在文件末尾添加以下内容。

export default {
//~略~
  }, //追記の際はこのカンマを忘れずに
  watchers: {
    webpack: {
      poll: true
    }
  }
}

接着我们将添加axios的设置。
axios是一个在node.js中运行的HTTP客户端,我们将使用它从nuxt.js中调用之前提到的API的URL。
由于在前面提到的nuxt的dockerfile中已经包含了这些内容,所以axios已经安装在容器中。
我们将在modules中添加以下内容,并添加axios。

export default {
//~略~
  modules: [
    '@nuxtjs/axios',
  ],
  axios: {
    baseURL: "http://localhost:8000"
  },
//~略~

为了简化操作,我们将编辑首页。
接下来,我们将对实际页面进行编辑。

<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
image.png

最后

我已经通过API实现了Django和Nuxt.js的简单集成。以上是开发环境的内容,我认为可能需要进行调整以用于生产环境。为了学习目的,我现在先发布此阶段的内容。

bannerAds