关于Django和React的建立和API协调~建立部分~

这篇文章是“AP通信2020年圣诞日历”的第13天的参赛作品。作为今年所做事情的总结,我将在此记录。

简要总结

本文的目的是介紹一種構建Web應用程序的方式,即使用Django作為後端,使用React作為前端。同時,為了實現從React中對Django數據庫的查詢和更新,我們還將使用Django REST框架對數據庫進行API化。最終的成品預期如下所示。

djare.png

在本次中篇,我跳过了Django与Apache的协作。您可以通过在运行服务器上运行Django来实现与正在运行的Apache的集成。参考资料:Django与Apache的协作。

因为变得比我想象中的长,所以关于使用React进行API数据更新的问题,我将在另一篇文章中讨论。

环境

在一台服务器上安装Django和React。数据库使用Django的默认选项(SQLite3),但也可以使用MySQL等其他选项。本次环境如下:
・CentOS7
・Python3.7
・Django3
・Node.js14

Django – Django

立即开始努力。这次我将在刚更新的全新Centos7上进行工作。
首先安装小工具。

[root@localhost ~]# yum install -y gcc zlib-devel libffi-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel libuuid-devel xz-devel wget

安装Python3

接下来安装Python3.7。
在使用Django3.0时,只要Python的版本是3.6或更高就没有问题,我们将从源代码进行安装。

[root@localhost ~]# wget https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tgz
[root@localhost ~]#tar xzf Python-3.7.9.tgz
[root@localhost ~]#cd Python-3.7.9
[root@localhost Python-3.7.9]#./configure --enable-optimizations
[root@localhost Python-3.7.9]#make altinstall
~~~~
Successfully installed pip-20.1.1 setuptools-47.1.0
[root@localhost Python-3.7.9]# python3.7 -V
Python 3.7.9

##ここでいちいちpython3.7と打つのが面倒なのでpython3で起動するようシンボリックリンクを設定する。
[root@localhost Python-3.7.9]# which python3.7
/usr/local/bin/python3.7
[root@localhost Python-3.7.9]# ln -s /usr/local/bin/python3.7 /usr/bin/python3
[root@localhost Python-3.7.9]# python3 --version
Python 3.7.9

##次にpipをインストールする。yumなどで入れると自動的に入るが、ソースからインストールすると入らない。
[root@localhost Python-3.7.9]# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
[root@localhost Python-3.7.9]# python3 get-pip.py
[root@localhost Python-3.7.9]# pip3 -V
pip 20.3.1 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)

安装Django和rest_framework

[root@localhost Python-3.7.9]# pip3 install Django
[root@localhost Python-3.7.9]# pip3 install djangorestframework

SQLite3的最新升级

下一步是将SQLite3更新到最新版本。原因是默认情况下,版本较低会在启动时引发错误。您可以在“https://www.sqlite.org/download.html”上确认当前的最新版本。

[root@localhost ~]# wget https://www.sqlite.org/2020/sqlite-autoconf-3340000.tar.gz
[root@localhost ~]# tar zxvf sqlite-autoconf-3340000.tar.gz
[root@localhost ~]# cd sqlite-autoconf-3340000
[root@localhost sqlite-autoconf-3340000]# ./configure --prefix=/usr/local
[root@localhost sqlite-autoconf-3340000]# make
[root@localhost sqlite-autoconf-3340000]# make install
[root@localhost sqlite-autoconf-3340000]# cd ..
[root@localhost ~]# find / -name sqlite3 
/root/Python-3.7.9/Doc/includes/sqlite3
/root/Python-3.7.9/Lib/sqlite3
/root/sqlite-autoconf-3340000/sqlite3
/usr/bin/sqlite3
/usr/lib64/python2.7/sqlite3
/usr/local/bin/sqlite3
/usr/local/lib/python3.7/site-packages/django/db/backends/sqlite3
/usr/local/lib/python3.7/sqlite3

##バージョンを確認する。
[root@localhost ~]# /usr/local/bin/sqlite3 --version 
3.34.0 2020-12-01 16:14:00 a26b6597e3ae272231b96f9982c3bcc17ddec2f2b6eb4df06a224b91089fed5b
[root@localhost ~]# /usr/bin/sqlite3 --version
3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668
[root@localhost ~]# sqlite3 --version
3.34.0 2020-12-01 16:14:00 a26b6597e3ae272231b96f9982c3bcc17ddec2f2b6eb4df06a224b91089fed5b
[root@localhost ~]# mv /usr/bin/sqlite3 /usr/bin/sqlite3_old
[root@localhost ~]# ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3
[root@localhost ~]# echo 'export LD_LIBRARY_PATH="/usr/local/lib"' >> ~/.bashrc
[root@localhost ~]# source ~/.bashrc
[root@localhost ~]# python3
Python 3.7.9 (default, Dec  7 2020, 23:13:43) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.34.0'
>>> exit()

创建Django项目

接下来,创建项目。

[root@localhost ~]# mkdir /home/django
[root@localhost ~]# cd /home/django/
[root@localhost django]# django-admin startproject django_react
[root@localhost django]# ls
django_react

##起動確認を行う。
[root@localhost ~]# cd django_react
[root@localhost django_react]# ls
django_react  manage.py
[root@localhost django_react]# python3 manage.py migrate
~~~~
  Applying sessions.0001_initial... OK
[root@localhost django_react]# python3 manage.py runserver

访问 http://localhost:8000/ 确认 Django 启动页面显示。

q1.png

我也会创建应用程序。顺便提一下,从这里开始,我会进行文件更新,所以个人建议准备好可以通过Remote连接使用vscode等工具会比较方便。不用每次都在服务器上用vi去更新文件。我是使用vscode的Remote SSH,在下面的方式下进行工作。

image.png
[root@localhost django_react]# python3 manage.py startapp react_app
[root@localhost django_react]# python3 manage.py startapp api
##apiは後ほどAPIを作成するときに使用する。

修改settings.py文件。

~~~~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'react_app',   #追加
]

我会确认所创建的应用程序是否正常运行。
我会持续更新react_app文件夹下的文件。

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the react_app index.")
##urls.pyはデフォルトでは作成されていないので作成すること。
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

更新django_react的urls。

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('react_app/', include('react_app.urls')),
]

运行`runserver`命令,并访问http://localhost:8000/react_app/,确保屏幕显示正常。

q3.png

Django的基本设置已经完成。

Django REST框架

增加设定

接下来进行API的准备工作。

~~~~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'react_app',   #追加
    'rest_framework', # 追加 
    'api.apps.ApiConfig', # 追加 
]
~~~~
# Setting permission
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}

数据库准备

准备将数据库转化为API。
由于这次只需要进行操作确认,所以我们随意创建一个用户表,并在其中插入一些测试数据。

from django.db import models

# Create your models here.

class User_Models(models.Model):

    class Meta:
        db_table = 'User'

    user_id = models.CharField(
        verbose_name='userid',
        blank=True,
        null=True,
        max_length=225,
        default='',
    )

    user_name = models.CharField(
        verbose_name='username',
        blank=True,
        null=True,
        max_length=225,
        default='',
    )

    user_age = models.CharField(
        verbose_name='userage',
        blank=True,
        null=True,
        max_length=225,
        default='',
    )

    user_email = models.CharField(
        verbose_name='useremail',
        blank=True,
        null=True,
        max_length=225,
        default='',
    )

    def __str__(self):
        return self.user_id
[root@localhost django_react]# python3 manage.py makemigrations
Migrations for 'react_app':
  react_app/migrations/0001_initial.py
    - Create model User_Models
[root@localhost django_react]# python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, react_app, sessions
Running migrations:
  Applying react_app.0001_initial... OK
[root@localhost django_react]# 

在管理界面中进行数据输入,因此需要在admin.py文件中进行记录。

from django.contrib import admin

from react_app.models import User_Models

admin.site.register(User_Models)

创建一个超级用户以便登录管理网站。

[root@localhost django_react]# python3 manage.py createsuperuser

创建后运行服务器,并访问http://localhost:8000/admin,在先前创建的超级用户账户登录。

q4.png
q5.png

在投入适当的测试数据。

路由和序列化设置

接下来需要进行路由配置和数据库的序列化。
在api应用文件夹下创建serializers.py文件,并按照以下方式进行编写。

from rest_framework import serializers
from react_app.models import User_Models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User_Models
        fields = ('user_id', 'user_name', 'user_age','user_email')

在views.py中,按以下方式进行描述。

from rest_framework import viewsets, routers
from react_app.models import User_Models
from .serializers import UserSerializer


class UserApi(viewsets.ModelViewSet):
    queryset = User_Models.objects.all()
    serializer_class = UserSerializer

    def get_queryset(self):
        queryset = User_Models.objects.all()
        L_id = self.request.query_params.get('id')

        if L_id:
            queryset = queryset.filter(user_id=L_id)
        return queryset

router = routers.DefaultRouter()
router.register(r'user', UserApi)

在这里稍作修改。具体来说,我让它可以通过URL查询进行搜索。当通过查询接收到ID时,我让它在数据库中进行ID搜索。实际操作稍后确认。

进行路由设置。
在项目的 URL 中按照以下方式添加。

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('react_app/', include('react_app.urls')),
    path('api/', include(views.router.urls)),
]

API准备就绪后,请运行服务器,并访问http://localhost:8000/api/user。若显示如下内容,则表示成功。

q7.png

试着给URL添加查询并进行搜索。
尝试访问http://localhost:8000/api/user/?id=1001。

q8.png

可以确认通过ID可以正确地进行搜索。

回应

安装

需要使用React,需要安装一个以上的Node.js版本。默认的版本可能较低,所以请参考https://github.com/nodesource/distributions/blob/master/README.md,在此安装最新版本的Node.js。本次安装选择版本14。

[root@localhost ~]# curl -sL https://rpm.nodesource.com/setup_14.x | bash -
[root@localhost ~]# yum -y install nodejs
[root@localhost ~]# node -v
v14.15.1
[root@localhost ~]# npm -v
6.14.8

##npm経由でyarnをインストールする
[root@localhost ~]# npm install -g yarn
[root@localhost ~]# yarn -v
1.22.10

接下来,使用 create-react-app 命令来创建一个 React 应用程序。
可以选择任何地方,但我选择在 /home/django 目录下创建。

[root@localhost django]# pwd
/home/django
[root@localhost django]# yarn create react-app django_front
~~~~
Happy hacking!
Done in 50.89s.
[root@localhost django]#

##動作確認を行う。
[root@localhost django]# cd django_front/
[root@localhost django_front]# yarn start

只需要一种选择,以下是对上述内容的中文本地化释义:

若能访问http://localhost:3000并显示以下页面,则说明初始设置已完成。

q9.png

React和Django的整合

到目前为止,Django和React分别在不同的环境中能够运行。
本文将演示如何将在React中创建的内容显示在Django中,就像最初的示意图中所示。在React中进行界面开发时,我们可以使用”yarn start”命令来实时查看构建的效果,并在构建完成后将其以静态文件的形式放置在Django的相应位置。

首先,在Django应用程序的一侧创建index.html文件。由于应用程序的文件夹越来越多了,所以要注意路径。

<!DOCTYPE html>

{% load static %}

<html lang="en">
<head>
    <meta charset="utf-8">
    <title>React</title>
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="{% static 'js/bundle.js' %}" ></script>
</body>
</html>

顺便提一下,在这个阶段访问http://localhost:8000/react_app/,没有任何显示。这是因为当前没有加载任何js文件。当在React中执行构建操作时,会自动放置js文件。

在React端进行构建准备。如果使用默认的yarn build命令进行构建,将会创建大量的文件。为了将构建后的文件合并成一个文件,安装并使用webpack。以下文章提供了关于webpack的详细信息。

注意:由于中文字符限制,无法提供完整的原文翻译,请以以上翻译内容为准。

参考资料:了解Webpack和Babel的基础知识。

安装所需的模块。

[root@localhost django_front]# yarn add @babel/preset-react babel-loader --dev

创建webpack.config.js。重要的是entry和output。将来如果要构建更多的文件,还需要适时添加module的配置。

const path = require('path');

module.exports = {
    mode: 'development',
    entry: './src/index.js', //buildするファイル
    output: {
        filename: 'bundle.js', //build後のファイル名
        path: path.join(__dirname, '../django_react/react_app/static/js') //buildファイルが作成される場所
    },
    module: {
        rules: [
          {
            test: /\.js[x]?$/,  
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: [
                  '@babel/preset-env',
                  '@babel/preset-react' 
                ],
                plugins: ['@babel/plugin-syntax-jsx'] 
              }
            }
          }
        ]
      },
      resolve: {
        extensions: ['.js', '.jsx', '.json']
      }
};

准备用React构建屏幕。

import React from "react";

const App = () => {
  return (
    <div>
      <p>React here!</p>
    </div>
  );
};
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById("app"));
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>React App</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

在这里创建一个.env文件,并按照下面的内容进行记录,然后运行yarn start。

SKIP_PREFLIGHT_CHECK=true
q10.png

如果出现这个画面就可以了。那就尝试构建吧。

[root@localhost django_front]# yarn webpack

然后会在 “/home/django/django_react/react_app/static/js” 目录下创建js文件。(同时也会自动创建文件夹)

如果访问 http://localhost:8000/react_app/,并且出现与刚才的 port3000 相同的界面,那就表示成功。

.env是什么意思?

刚刚创建了.env文件,其意义在于在yarn start时跳过包之间的依赖关系检查。原因是babel-loader的版本升级后,如果不创建.env文件并执行yarn start,则会触发依赖检查并导致无法启动。这次为了强行跳过依赖检查。但在之后的构建过程中,我们不确定会有什么影响,所以这是一个应该尽早解决的问题。(本文中将跳过依赖检查)

概述

在本文中,我们搭建了Django和React的环境,并且已经成功实现了在Django中显示React应用程序的功能。
实际上,对于环境搭建部分,我们本来想通过使用Docker和Ansible进行自动化来完成,但是由于时间紧迫而放弃了。对于这一点,我们打算另外来做。
接下来,我们将进行设置,以便从React通过API访问和更新Django的数据库。

广告
将在 10 秒后关闭
bannerAds