UbuntuでDjangoの画像と静的資産を管理する

このチュートリアルでは、**Django** フレームワークを使ってウェブのユーザー体験を向上させるために **django**.contrib.staticfiles モジュールを効果的に使う方法を紹介します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/how-to-manage-django-images-and-static-assets-on-ubuntu-18-04_594696)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*


#目的
以下のチュートリアルの目標は以下の通りです。

- django フレームワークを使って画像や静的ファイルを提供する方法を示します。
- collectstatic コマンドを使用してイメージと静的ファイルを本番環境にデプロイする方法を示します。

#前提条件
- ubuntu 18.04がインストールされたコンピュータまたは仮想マシンにアクセスしている
- IDEにアクセスできる

#ステップ1: プロジェクトの初期化と設定
####1.1.  環境の初期化
開発環境の設定については、ここで紹介した手順で行います。

1、 必要なライブラリのインストール

```
$ sudo apt install python3             # Install Python3 interpreter
$ sudo apt install python3-pip         # To manage python packages
$ sudo apt install python3-virtualenv  # To manage virtual python environments
$ sudo apt install apache2             # To serve images and static assets
```

2、 仮想環境を作成してアクティベートする

```
$ virtualenv --python=python3 venv     # This create the virtual environment venv
$ source venv/bin/activate             # This is to activate the virtual environment
```

3、 プロジェクトの依存関係のインストール

```
(venv)$ pip install Django==2.1            # Install Django v2.1
(venv)$ pip install Pillow                 # To manage images through Python code
(venv)$ pip install easy_thumbnails        # To easyly manage image thumbnails
```

**注**：venv という名前の隔離された仮想環境の中で ruunning していることを示すために venv サフィックスが追加されています。

####1.2.  プロジェクトの設定
1、 djangoプロジェクトの**フォトギャラリー**を作成する

```
(venv)$ django-admin startptoject photogallery
```

2、 djangoアプリケーション**ギャラリー**を作成する

```
(venv)$ cd photogallery/
(venv)$ django-admin startapp gallery
```

3、 プロジェクトの**フォトギャラリー**に**ギャラリー**アプリを追加

そのためには、フォトギャラリープロジェクトのsettings.pyファイルにギャラリーアプリを追加する必要があります。

```
INSTALLED_APPS = [
    ...
    'photogallery.gallery'
    ...
]
```
4、移行データをデータベースに保存する

```
(venv)$ pyhton manage.py migrate
```
5、 ジャンゴ管理者ダッシュボードアプリケーションのスーパーユーザーを作成する

```
(venv)$ python manage.py createsuperuser --username admin
(venv)$ Email address: yourmail@web.com
(venv)$ Password:
(venv)$ Password (again):
```

6、  これを実行すると、プロジェクトフォルダの構造は以下のようになります。

```
.
├── db.sqlite3
├── gallery
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── socialgallery
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```

7、 すべてがうまく機能していることを確認してください。

```
(venv)$ python manage.py runserver
...
Starting development server at http://127.0.0.1:8000/
...
```

#ステップ2: 静的ファイルサーバの設定
1、 プロジェクトの **settings.py** ファイル内の **INSTALLED_APPS** にアプリケーション **django.contrib.staticfiles** を追加します。

```
INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles'
    ...
]
```

2、 静的ファイル用のフォルダを作成し、正しいパーミッションを設定します。

```
# Create static folders on the webserver
(venv)$ sudo mkdir /var/www/static
(venv)$ sudo mkdir /var/www/media
# Make static folders editable from the web browser
(venv)$ sudo chown -R www-data:www-data /var/www/static 
(venv)$ sudo chown -R www-data:www-data /var/www/media 
# Allow the group to write to the directory with appropriate permissions
(venv)$ sudo chmod -R 777 /var/www/static                   
(venv)$ sudo chmod -R 777 /var/www/media                   
# Add myself to the www-data group
(venv)$ sudo usermod -a -G www-data $(whoami)
```
3、  静的ファイルを提供するためにプロジェクトを構成します。

```
STATIC_URL = '/static/'              # Used to include static resources in web pages
STATIC_ROOT = '/var/www/static/'     # Used to get static resources from web server
MEDIA_URL = '/media/'                # Used to include media items in web pages
MEDIA_ROOT = '/var/www/media/'       # Used to get media items from web server
```

4、  画像および静的ファイルを STATIC_URL から STATIC_ROOT に、MEDIA_URL から MEDIA_ROOT に移行する。

```
# This command will copy everything from the STATIC_URL to the STATIC_ROOT
(venv)$ python manage.py collectstatic
```

**注**：このコマンドは、ユーザが追加した新しい静的ファイルを考慮してアプリケーションをデプロイするたびに実行する必要があります。

#ステップ3: 画像と静的ファイルの使用
ウェブページで画像ファイルや静的ファイルを使用するには、該当するページで静的モジュールをプリロードする必要があります。そのためには、以下のコードをルートページの**base.html**に追加します。

```
{% load static %}
```

次に、このような方法でホームページにイマエを入れることができます。

```
<img src={% static 'gallery/images/background.jpg' alt='Background Image' %}>
```

そして、これらのタグを含めることで、静的アセットをウェブページに追加することができます。

```
{% static 'gallery/css/bootstrap.css'%}
{% static 'gallery/js/bootstrap.js'%}
{% static 'gallery/js/jquery.js'%}
```

#ステップ4：データモデルの定義
本題から離れないように、ユーザーがアップロードした画像を管理するためのデータモデルを1つだけ作成します。

1、  以下は、**gallery/models.py**ファイルの内容です。

```
from django.db import models
from django.contrib.auth.models import User

class Image(models.Model):
    name = models.TextField(max_length='100')
    path = models.ImageField()
    number_views = models.IntegerField(default=0)

    def __str__(self):
        return self.name
```

2、  モデルをデータベースに保存

```
(venv)$ python manage.py make migrations    # This command will create migrations files
(venv)$ python manage.py migrate            # Here the migrations created are executed
```

#ステップ5：ビューの書き方
ビューはユーザがアプリケーションとどのように対話するかを定義します。

ビューはファイル: **socialgallery/gallery/views.py**で作成されます。

```
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, DetailView, \
     UpdateView, DeleteView
from .models import Image

class ImageListView(ListView):
    model = Image
    template_name = 'gallery/image_list.html'
    
class ImageDetailView(DetailView):
    model = Image
    template_name = 'gallery/image_detail.html'

class ImageCreateView(CreateView):
    model = Image
    template_name = 'gallery/image_create.html'
    fields = '__all__'

class ImageUpdateView(UpdateView):
    model = Image
    template_name = 'gallery/image_update.html'
    fields = '__all__'

class ImageDeleteView(DeleteView):
    model = Image
    template_name = 'gallery/image_delete.html'
    success_url = reverse_lazy('image-list')
```
#ステップ6：URLの定義
ここで作成したビューにアクセスするためには、URLルートを設定しなければなりません。これらのルートは**gallery/urls.py**ファイルの中で設定しますので、もしこのフォルダがアプリのフォルダに存在しない場合は、続ける前に作成してください。

**gallery/urls.py**ファイルの内容は以下の通りです。

```
from django.urls import path
from .views import ImageListView, ImageDetailView, ImageCreateView, \
    ImageUpdateView, ImageDeleteView

urlpatterns = [
    path('', ImageListView.as_view(), name='image-list'), # Will serve as homepage
    path('<int:pk>', ImageDetailView.as_view(), name='image-detail'),
    path('create', ImageCreateView.as_view(), name='image-create'),
    path('update/<int:pk>', ImageUpdateView.as_view(), name='image-update'),
    path('delete/<int:pk>', ImageDeleteView.as_view(), name='image-delete'),
]
```

そして、**gallery/urls.py** ファイルをプロジェクトの urls ファイル **photogallery/urls.py** に追加します。

以下はファイル**socialgallery/urls.py**の内容です。

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

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

#ステップ7：HTMLテンプレートの作成
HTMLテンプレートの作成には、**views.py**ファイルで指定したHTMLテンプレートをDjangoが見つけるテンプレートフォルダを作成する必要があります。

```
(venv)$ mkdir gallery/templates templates/gallery 
```

ギャラリーテンプレートファイルの中に、以下のhtmlファイルを作成します。

1、**templates/gallery/image_list.html**

```
{% block content %}
    <h2>Images</h2>
    <ul>
        {% for image in object_list %}
            <li>{{ image.name }} - {{ image.path }} </li>
        {% endfor %}
    </ul>
{% endblock %}
```

2、**templates/gallery/image_detail.html**

```
<p>Image</p>
<p>name: {{ object.name }}</p>
<p>Path: {{ object.path }}</p>
<p>Views: {{ object.number_views }}</p>
```

3、**templates/gallery/image_create.html**

```
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save Image">
</form>
```

4、**templates/gallery/image_update.html**

```
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Update User">
</form>
```

5、**templates/gallery/image_delete.html**

```
<form method="post">
    {% csrf_token %}
    <p>Are you sure you want to delete the image "{{ object.name }}"?</p>
    <input type="submit" value="Confirm">
</form>
```

#ステップ8：管理者ダッシュボードの設定
ギャラリーアプリの管理者ダッシュボードを設定するには、**gallery/admin.py**ファイルを修正して、内部にこのコードを追加しなければなりません。

```
from django.contrib import admin
from .models import Image

@admin.register(Image)
class ImageAdmin(admin.ModelAdmin):
    model = Image
```

#ステップ9：すべてがうまく機能するかどうかのテスト
すべてが正常に動作することをテストするには、コマンドを使用して開発サーバーを起動する必要があります。

```
(venv)$ python manage.py runserver
```

#結論
このチュートリアルの最後まで来て、Django での静的リソースの使用例、統合、使用、サービスを見てきました。私たちは、画像を管理するアプリケーションを開発する際に考慮すべき設定と、これらすべてのファイルの安全なデプロイを確保する方法を見てきました。

以下はオンラインで公開されているアプリケーションのソースコードのリンクです。

[https://github.com/binel01/photogallery.git](https://github.com/binel01/photogallery?spm=a2c65.11461447.0.0.4f4458ccFZa8Ru&file=photogallery.git)

#続きを読む
- 画像の管理に使われるパッケージ: django-easythumbnails, [Django パッケージ](https://djangopackages.org/grids/g/photos/?spm=a2c65.11461447.0.0.4f4458ccFZa8Ru)のサイトを参照しています。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*