62
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-02-09

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

ImageField

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

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

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

models.py
model.objects.delete(False)

とすれば良いようです。

私も知りませんでした。

ImageKit

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

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

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

console
pip install -U django-imagekit

でインストールできます。

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

console
pip install -U Pillow

しましょう。

djangoのsettings.pyINSTALLED_APPSimagekitを追記してください。

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

ImageKitとは

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

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

Models.py

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

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

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}
                            )

テンプレート

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

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>

また、生成される画像は

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

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

settings.py
MEDIA_URL = "/media/"  # 例
# /media/CACHE/...

から配信されます。

views.py

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

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です。

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"を忘れるとアップロードされませんので気をつけましょう。
2・3時間無駄にしました。何度もしました。

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だけ読むだけで十分に使用可能だと思います。

62
66
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?