Skip to content

Instantly share code, notes, and snippets.

@voluntas
Last active May 13, 2022 13:46
Show Gist options
  • Save voluntas/7002085 to your computer and use it in GitHub Desktop.
Save voluntas/7002085 to your computer and use it in GitHub Desktop.
S3 と非同期サムネイル作成 コトハジメ

S3 と非同期サムネイル作成 コトハジメ

更新:2013-11-04
バージョン:0.0.0
作者:@voluntas
URL:http://voluntas.github.io/

概要

  • 画像のアップロード先を S3 にして欲しい
  • アップロードと同時にサムネイルを生成して欲しい
  • サムネイル生成は非同期であって欲しい

この 3 つの願いはよくある話なのではないでしょうか。 王道なのかも知れませんがこの辺の処理がまとまっていなかったのでまとめてみました。

ゴール

  • S3 アップロードには django-storages
  • サムネイル生成には django-imagekit
  • 非同期処理には django-celery

これらの 3 つを組み合わせることで画像を S3 にアップロードし、 非同期にサムネイルを生成するという処理を実現させます。

セットアップ

必須:

$ pip install django django-celery django-magekit django-storages boto redis Pillow celery

おまけ:

$ pip install flower

Pillow はイメージ変換ライブラリだが、libjpeg 等が必要なのでなんとか動くようにすること

macports:

$ sudo port install libjpeg-turbo

yum:

$ sudo ...

aptitude:

$ sudo ...

サンプルソースコード

  • ジェネリックビューは使ってない
  • HTML は凄く適当
# coding=utf8

from django.shortcuts import render, redirect

from .models import Entry
from .forms import EntryForm


def home(request):
    entries = Entry.objects.all()
    return render(request, 'rime/home.html', {'entries': entries})


def upload(request):
    if request.method == 'POST':
        form = EntryForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('/')
    else:
        form = EntryForm()
    return render(request, 'rime/upload.html', {'form': form})

project/core/models.py

# coding=utf8

from django.db import models

from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Entry(models.Model):
    title = models.CharField(max_length=255)
    img = models.ImageField(upload_to='entry/%Y/%m/%d')
    img_thumbnail = ImageSpecField(source='img',
                                   processors=[ResizeToFill(100, 50)],
                                   format='JPEG',
                                   options={'quality': 60})
    class Meta:
        ordering = ('title', )

    def __unicode__(self):
        return self.title

project/core/forms.py

# coding=utf8

from django import forms

from .models import Entry

class EntryForm(forms.ModelForm):
    class Meta:
        model = Entry

project/core/templates/core/home.html

{% for entry in entries %}
    <div><img src="{{ entry.img_thumbnail.url }}"><br></div>
{% endfor %}

project/core/templates/core/upload.html

<form action="/upload" method="post" enctype="multipart/form-data">{% csrf_token %}
    {% for field in form %}
        <div >
            {{ field.errors }}
            {{ field.label_tag }}: {{ field }}
        </div>
    {% endfor %}
    <p><input type="submit" value="アップロード" /></p>
</form>

project/core/settings.py

INSTALLED_APPS = (
    ...

    'djcelery',
    'imagekit',
    'storages',

    'core',
)

DEFAULT_FILE_STORAGE = 'core.s3.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 'core.s3.StaticRootS3BotoStorage'

AWS_S3_SECURE_URLS = True
AWS_QUERYSTRING_AUTH = False

AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_STORAGE_BUCKET_NAME = ''

IMAGEKIT_DEFAULT_FILE_STORAGE = DEFAULT_FILE_STORAGE
IMAGEKIT_DEFAULT_CACHEFILE_BACKEND = 'imagekit.cachefiles.backends.Async'

import djcelery
djcelery.setup_loader()

BROKER_URL = 'redis://localhost:6379/0'

project/core/s3.py

# coding=utf8

from storages.backends.s3boto import S3BotoStorage

StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage  = lambda: S3BotoStorage(location='media')

project/core/urls.py

# coding=utf8

from django.conf.urls import patterns, url

urlpatterns = patterns('',
    url(r'^$', 'rime.views.home', name='home'),
    url(r'^upload$', 'rime.views.upload', name='upload'),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment