Webアプリケーション開発のお勉強 #3

#1.この記事の内容

[Webアプリケーション開発のお勉強 #2](https://qiita.com/ryoma-jp/items/e7437de22541355c3d65)でサーバの起動までを記載しました．
本記事ではフロントエンドの実装としてBootstrapの導入について記載します．

Bootstrapの導入方法は，下記に示す例のようにインストール方法がいくつかあります．

* コンパイル済みのCSS/JSをインストールする
* ソースコードを運用環境でコンパイルしてインストールする
* [jsDelivr](https://www.jsdelivr.com/)から配信されるインストール済みのコードを使用する
* パッケージマネージャを用いてインストールする

今回はオンプレミス環境でもアプリケーションを実行できるよう，コンパイル済みのCSS/JSをダウンロードして組込みます．
本記事では，Bootstrap公式からダウンロードできるダッシュボードのサンプルを動かすまでの手順を記載します．

#2.Bootstrap導入手順

##2-1.Django-Bootstrap5アプリケーションの構築

PyPiで公開されている[django-bootstrap5](https://pypi.org/project/django-bootstrap5/)をvirtualenv上に導入し，アプリケーションのベースとするコードを生成します．
ここに，実装するHTMLと接続します．

```
$ cd <path/to/project>
$ source venv/bin/activate
(venv)$ pip3 install django_bootstrap5 psycopg2-binary
(venv)$ cd django_project/
(venv)$ export ALLOWED_HOSTS="localhost 127.0.0.1 [::1]"
(venv)$ python3 manage.py startapp app
(venv)$ cd ..
(venv)$ deactivate
$ vim django_project/requirements.txt
$ vim django_project/project/settings.py
$ vim django_project/project/urls.py
$ vim django_project/app/views.py
$ touch django_project/app/urls.py
$ mkdir django_project/html
$ touch django_project/html/index.html
```

<details><summary>django_project/requirements.txtの編集内容</summary>
<div>

```
@@ -1,3 +1,4 @@
 Django
 psycopg2-binary
 gunicorn
+django-bootstrap5
```

</div>
</details>

<details><summary>django_project/project/settings.pyの編集内容</summary>
<div>

```
@@ -40,6 +40,8 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
+    'django_bootstrap5',
+    'app',
 ]

 MIDDLEWARE = [
@@ -57,7 +59,7 @@ ROOT_URLCONF = 'project.urls'
 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
+        'DIRS': [BASE_DIR, 'html'],
         'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
```

</div>
</details>

<details><summary>django_project/project/urls.pyの編集内容</summary>
<div>

```
@@ -14,8 +14,9 @@ Including another URLconf
     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
 """
 from django.contrib import admin
-from django.urls import path
+from django.urls import path, include

 urlpatterns = [
     path('admin/', admin.site.urls),
+    path('', include('app.urls')),
 ]
```

</div>
</details>

<details><summary>django_project/app/views.pyの編集内容</summary>
<div>

```
@@ -1,3 +1,9 @@
 from django.shortcuts import render

 # Create your views here.
+
+""" Function: index
+ * show index
+"""
+def index(request):
+    return render(request, 'index.html')
+
```

</div>
</details>

<details><summary>django_project/app/urls.pyの内容</summary>
<div>

```
"""app URL Configuration
"""
from django.urls import path
from . import views

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

</div>
</details>

<details><summary>django_project/html/index.htmlの内容</summary>
<div>

```
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>
```

</div>
</details>

ここまでの対応で，サーバを起動し，http://localhost:1317 へアクセスすると，index.htmlに記述した下図が表示されます．
次節で，index.htmlの内容をBootstrap公式に公開されているダッシュボードのサンプルページに更新します．

```
$ docker-compose build
$ docker-compose up -d
```

![index_helloworld.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/983907/d00e200c-daf6-9183-fd64-c0790312d117.png)


##2-2.ダッシュボードのサンプルの組込み

Bootstrapは[公式ホームページのダウンロードページ](https://getbootstrap.jp/docs/5.0/getting-started/download/)または[GitHubのreleaseページ](https://github.com/twbs/bootstrap/releases)から取得することができます．
今回は，サンプルコードもダウンロードする為，GitHubからダウンロードする手順を記載します．

なお，本記事で動作確認を行ったのは[v5.1.1](https://github.com/twbs/bootstrap/releases/tag/v5.1.1)です．

```
$ cd <path/to/project>
$ mkdir django_project/static
$ cd django_project/static
$ wget https://github.com/twbs/bootstrap/releases/download/v5.1.1/bootstrap-5.1.1-dist.zip
$ unzip bootstrap-5.1.1-dist.zip
$ mv bootstrap-5.1.1-dist/* .
$ wget https://github.com/twbs/bootstrap/releases/download/v5.1.1/bootstrap-5.1.1-examples.zip
$ unzip bootstrap-5.1.1-examples.zip
$ cp bootstrap-5.1.1-examples/dashboard/dashboard.css ./css
$ cp bootstrap-5.1.1-examples/dashboard/dashboard.rtl.css ./css
$ cp bootstrap-5.1.1-examples/dashboard/dashboard.js ./js
$ cp bootstrap-5.1.1-examples/dashboard/index.html ../html/index.html
$ rm -rf bootstrap-5.1.1-dist.zip bootstrap-5.1.1-dist bootstrap-5.1.1-examples.zip bootstrap-5.1.1-examples
$ cd ../..
$ vim django_project/html/index.html
```

<details><summary>django_project/html/index.htmlの編集内容</summary>
<div>

```
@@ -1,3 +1,4 @@
+{% load static %}
 <!doctype html>
 <html lang="en">
   <head>
@@ -13,7 +14,7 @@


     <!-- Bootstrap core CSS -->
-<link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">
+<link href="{% static '/css/bootstrap.min.css' %}" rel="stylesheet">

     <style>
       .bd-placeholder-img {
@@ -33,7 +34,7 @@


     <!-- Custom styles for this template -->
-    <link href="dashboard.css" rel="stylesheet">
+    <link href="{% static '/css/dashboard.css' %}" rel="stylesheet">
   </head>
   <body>

@@ -278,8 +279,10 @@
 </div>


-    <script src="../assets/dist/js/bootstrap.bundle.min.js"></script>
+    <script src="{% static '/js/bootstrap.bundle.min.js' %}"></script>

-      <script src="https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/feather.min.js" integrity="sha384-uO3SXW5IuS1ZpFPKugNNWqTZRRglnUJK6UAZ/gxOX80nxEkN9NcGZTftn6RzhGWE" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js" integrity="sha384-zNy6FEbO50N+Cg5wap8IKA4M/ZnLJgzc6w2NqACZaK0u0FXfOWRRJOnQtpZun8ha" crossorigin="anonymous"></script><script src="dashboard.js"></script>
+      <script src="https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/feather.min.js" integrity="sha384-uO3SXW5IuS1ZpFPKugNNWqTZRRglnUJK6UAZ/gxOX80nxEkN9NcGZTftn6RzhGWE" crossorigin="anonymous"></script>
+      <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js" integrity="sha384-zNy6FEbO50N+Cg5wap8IKA4M/ZnLJgzc6w2NqACZaK0u0FXfOWRRJOnQtpZun8ha" crossorigin="anonymous"></script>
+      <script src="{% static '/js/dashboard.js' %}"></script>
   </body>
 </html>
```

</div>
</details>

ここまでの対応でサーバを起動すると下図のBootstrap公式のダッシュボードのサンプルが表示されます．
サンプルページはDashboardメニューのみで，ページの遷移などは実装されていません．
また，CSS/JSのCore部分はオンプレミス環境で動作するように実装していますが，サンプルページで使用する「feather.min.js」及び「Chart.min.js」はjsDelivrから取得するように実装しています（Bootstrap公式の実装から変更を加えていません）．

![index_dashboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/983907/b6717899-3965-aef1-8fd0-4c54b461ae69.png)


#3.さいごに

BootstrapのCSS/JSをオンプレミス環境で動作するように組み込み，ダッシュボードのサンプルページを表示するところまでを実装しました．
次回は機械学習を行うため，WebアプリケーションサーバでGPUを認識する手順を記載する予定です．

#4.関連リンク

* [Webアプリケーション開発のお勉強　目次](https://qiita.com/ryoma-jp/items/1a0a438313dcb30ef6fc)
* [著者GitHubのReferenceに記載のリンク](https://github.com/ryoma-jp/AI_Dashboard#reference)