16
9

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.

Django2で画像を指定サイズで保存する django-stdimage

Posted at

はじめに

Djangoの画像アップロードは、標準機能のImageFieldを使うべしと、Django公式や先人のブログに書かれていた。
しかし、models.pyImageFieldを用いて、画像アップロード、そして画面に表示することを試したところ、サイズがバラバラであることにショックを受けた。
画像サイズを均一にして、アップロードすれば問題ないと思うのだが、ひと手間かけることも馬鹿馬鹿しいと思った。

そこで保存時なのか表示時なのかでリサイズできないか調べていたところ、django-stdimageに出会った。
だが、日本語ドキュメントが見つからず、本家Githubページ( https://github.com/codingjoe/django-stdimage )を読んで、簡単にまとめることにした。

環境

Windows10
Python 3.6.0
Django 2.1.1

Pillowのインストール

ImageField(stdimage)を扱う上で、Pillowをインストールする。
>pip list Pillow

django-stdimageのインストール

django-stdimage(Django Standardized Image Field)をインストールする。
>pip install django-stdimage

settings.pyの編集

INSTALLED_APPにdjango-stdimageを使用することを伝える。

settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'news',
    'stdimage',  #追記
]

models.pyの編集

Modelに属性を追記する。
画像のアップロード先 upload_to は環境に合わせて記載する。

models.py
from django.db import models
from stdimage.models import StdImageField  #追記


class Post(models.Model):
    title = models.CharField(max_length=150)
    text = models.TextField(blank=True)

    # 以下を追記
    image = StdImageField(upload_to='path/to/img', blank=True, variations={
        'large': (600, 400),
        'thumbnail': (100, 100, True),
        'medium': (300, 200),
    })

マイグレーションを実行

modelを編集したら、マイグレーションファイルを作成し、
>python manage.py makemigrations news
※「news」は各自のアプリ名に読み替える必要あり。

マイグレーションを行い、データベースに反映する。
>python manage.py migrate

テンプレートの編集

ここでは、ニュース一覧の表示を例とした。
投稿日、タイトル、本文、そして画像を表示する。
models.pyのPostクラスにおいて、imageblank=Trueのため、画像がない場合は非表示にする。

index.html

{% extends 'news/base.html' %}

{% block content %}

    {% for post in posts %}

    <div>
        {{ post.created_datetime }}
    </div>
    <div>
        <h1><a href="{% url 'news:detail' pk=post.pk  %}">{{post.title}}</a></h1>
        <p>{{ post.text|truncatechars:100 }}</p>
        
        # 画像がある時のみ表示
        {% if  post.image %} 
            <p><a href="{{ post.image.url }}"><img alt="" src="{{ post.image.thumbnail.url }}"/></a></p>
        {% endif %}
    
    </div>

    {% endfor %}

{% endblock content %}

こんな感じになる。
「aaa」と「bbb」はサムネイルサイズの画像を表示。
「ccc」は画像なし。

image01.PNG

models.pyのPostクラスにおいて、thumbnail、medium、largeの3サイズでデータベースに保存するようにした。
ニュース詳細ページで、各サイズの画像を表示してみる。
テンプレートは以下の通り。

detail.html

{% extends 'news/base.html' %}

{% block content %}

<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaks }}</p>
{% if post.image %}
<p><a href="{{ post.image.url }}"><img alt="" src="{{ post.image.thumbnail.url }}"/></a></p>
<p><a href="{{ post.image.url }}"><img alt="" src="{{ post.image.medium.url }}"/></a></p>
<p><a href="{{ post.image.url }}"><img alt="" src="{{ post.image.large.url }}"/></a></p>
{% endif %}

{% endblock content %}

こんな感じになる。
thumbnail、medium、largeの3サイズが表示できている。
image02.PNG

おわりに

Djangoの画像サイズを指定して保存するやり方は複数あるようだ。
軽く調べたところ、ImageKitやsorl-thumbnail、stdimageなどがあった。
(はじめに、django-thumbsを使おうとしたが、python2のみの対応であることに途中で気づきました。。。)
色々な方法を試してみたい。

16
9
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
16
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?