入力エラー時にアップロードファイルをキャッシュに保持するdjango-file-resubmit

フォーム入力エラーのとき、フォームを再描画してエラーメッセージを表示することになりますが、ファイルのアップロードがある場合、その入力値はクリアされますので、もう一度選ぶことになります。

django-file-resubmitはファイルをキャッシュにキープして、再入力する手間を省けるようにするライブラリです。


un1t/django-file-resubmit · GitHub


インストール

pip install django-file-submit


INSTALLED_APPSにfile_resubmitを追加

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'apps',
    'file_resubmit'
)


cacheの設定を追加します

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
    "file_resubmit": {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        "LOCATION": '/tmp/file_resubmit/'
    },
}


MEIDA_ROOTとか

import os
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'upload')
MEDIA_URL = 'http://localhost:8000/upload/'


modelに画像フィールドをもたせます。

models.py

class Person(models.Model):
    name = models.CharField(max_length=100)
    icon = ImageField(upload_to='/tmp/icons')

    @models.permalink
    def get_absolute_url(self):
        return ('apps_person_detail', (), {'pk': self.pk})


formでwidgetを指定します。
forms.py

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person

        widgets = {
            'icon': AdminResubmitImageWidget(),
        }


views.py

class PersonCreateView(CreateView):
    model = Person
    form_class = PersonForm


class PersonDetailView(DetailView):
    model = Person


テンプレート
画像をアップロードするのでenctype="multipart/form-data"を忘れずに追加


person_form.html

{% extends "base.html" %}

{% block content %}

{% if form.errors %}<h1>Please correct the following errors</h1>{% else %}<h1>Submit</h1>{% endif %}

<form enctype="multipart/form-data" action="" method="post">{% csrf_token %}
<table>
{{ form }}
</table>

<p><input type="submit" value="submit" /></p>
</form>

{% endblock %}

person_detail.html

{% extends "base.html" %}

{% block content %}
<p>{{ object.name }}</p>
<p><img src="{{ object.icon.url }}" /></p>

{% endblock %}


urls.py

    url(r'^person/create/?$', PersonCreateView.as_view(), name='apps_person_create'),
    url(r'^person/(?P<pk>\d+?)/$', PersonDetailView.as_view(), name='apps_person_detail'),
    url(r'^upload/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),

使ってみる

nameを入れ忘れて、入力エラーになった。

画像名が表示されているのが確認できます。


nameをいれてsubmit


保存されました!