DjangoでImageFieldからサムネイルをImageKitで自動生成する

Djangoでイメージを使う場合について。

# ImageField

DjangoはImageFieldというフィールドを定義することができます。
これはFileFieldを継承したフィールドです。

詳しい使い方は
http://qiita.com/kojionilk/items/da20c732642ee7377a78
こちらにとても良くまとまっています。

ただ、レコードを削除するときに単純にファイルを削除したい場合は、

```py3:models.py
model.objects.delete(False)
```

とすれば良いようです。

https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.fields.files.FieldFile.delete

私も知りませんでした。

# ImageKit

さて、ウェブでイメージを扱う場合、ただ保存するだけでは不足です。
サムネイル・大きなイメージなどなど、様々な画質・大きさの画像を用意する必要があります。

しかし、自前で作るとなるとめんどくさい・・・

ということでImagekitの登場となります。

https://github.com/matthewwithanm/django-imagekit

```bash:console
pip install -U django-imagekit
```
でインストールできます。

Pillow必須なので、インストールしていない方は

```bash:console
pip install -U Pillow
```
しましょう。

djangoの`settings.py`の`INSTALLED_APPS`に`imagekit`を追記してください。

これで使えるようになります。

## ImageKitとは

ImageKitは、ファイルをアップロードすると、モデルに設定した品質・大きさに画像を変換してくれるモジュールです。

処理自体は最初にテンプレートが呼ばれる時に行われているような気がします。

### Models.py

こんな感じで定義します。

`ImageField`を定義していますが、これが元になるフィールドです。
他のフィールドはImageKitの設定です。リサイズする際の大きさや、品質を定義します。

```python:models.py
from django.db import models
from imagekit.models import ImageSpecField, ProcessedImageField
from imagekit.processors import ResizeToFill


class Image(models.Model):

    origin = models.ImageField(upload_to="photos/%y/%m/%d/")

    big = ImageSpecField(source="origin",
                         processors=[ResizeToFill(1280, 1024)],
                         format='JPEG'
                         )

    thumbnail = ImageSpecField(source='origin',
                            processors=[ResizeToFill(250,250)],
                            format="JPEG",
                            options={'quality': 60}
                            )

    middle = ImageSpecField(source='origin',
                        processors=[ResizeToFill(600, 400)],
                        format="JPEG",
                        options={'quality': 75}
                        )

    small = ImageSpecField(source='origin',
                            processors=[ResizeToFill(75,75)],
                            format="JPEG",
                            options={'quality': 50}
                            )
```

### テンプレート

テンプレートの記載例です。

```jinja:template.html
<ul class="list-unstyled image-list">
    {% for image in image_list %}
    <li>
        <a href="{% url 'image_detail' image.id %}">
            <img src="{{ image.thumbnail.url }}" width="250">
        </a>
    </li>
    {% endfor %}
</ul>
```

また、生成される画像は

```python:settings.py
MEDIA_ROOT = os.path.join(ROOT_DIR, "media")  # 例
# ROOT_DIR/media/CACHE/...
```

MEDIA_ROOTの中に```CACHE```ディレクトリを生成して保存されます。したがって、URLも

```python:settings.py
MEDIA_URL = "/media/"  # 例
# /media/CACHE/...
```
から配信されます。

### views.py

素晴らしいことに、views.pyでは何もすることはありません。
いつも通りにしておけば、ImageKitがよしなに処理してくれます。

```python:views.py
from django.views.generic import ListView

from images.models import Image


class ImageListView(ListView):
    model = Image
    context_object_name = 'image_list'
```


### forms.py

フォームも何も変わることはありません。
いつものファイルアップロードフォームでOKです。

```python:forms.py
from django.forms import ModelForm
from images.models import Image

class UploadFileForm(ModelForm):
    class Meta:
        model = Image
        fields = ["origin", ]
```

テンプレートにフォームを記述するときは`enctype="multipart/form-data"`を忘れるとアップロードされませんので気をつけましょう。
２・３時間無駄にしました。何度もしました。

```jinja:upload.html
{% extends 'base.html' %}

{% block content %}

<form method="POST" action="{% url 'image_upload' %}" enctype="multipart/form-data">
  {% csrf_token %}
  {% load crispy_form_tags %}
  {{ form|crispy }}

  <button class="btn btn-primary" type="submit">アップロード</button>
</form>

{% endblock %}
```

#　まとめ

他にも便利なフィールドがあるようですが、それは割愛します。
githubのREADMEだけ読むだけで十分に使用可能だと思います。