forms.ImageFieldで初期値を表示したい
models.ImageFieldで保存されたデータでは、DjangoAdminで編集する際に、オブジェクトが渡されてURLが表示されるようになっているのですが、これをforms.ImageFieldでやろうとすると、formの__init__関数で初期値を入れてあげることは分かっても、何を渡してあげれば良いのかで困ってしまいました。
まずは自作フォームのおさらい
とりあえず、ModelFormを継承して、オリジナルのフォームも追加してみます。
モデル名Sampleで、Sampleには存在しないフィールド名imgをフォームとして追加してあげる例です。
class SampleForm(forms.ModelForm): img = forms.ImageField( required=False, widget=forms.ClearableFileInput(attrs={'class': 'form-control-file'}), label='画像' ) class Meta: model = Sample
実際に使用する際には、save関数なりで、imgの値を取り出して何かしてあげる必要があります。
今回、自分がやっていたこととしては、画像ファイルをs3にアップロードして、そのurlのみを別フィールドに保存していました。
forms.ImageFieldに初期値を入れてあげる
上記で作成したSampleFormの__init__関数で初期値を入れます。この際に入れてあげる初期値はImageFieldFileのオブジェクトでなくてはならない。
自分の場合は、上記のとおり、imgをurlとして保存していて、それをImageFieldFileに設定すると以下のような感じになりました。もし、models.ImageFieldのオブジェクトを使用して別フィールドを作る際には、instanceに渡せばいいんじゃないかなと思います。
from django import forms from django.db.models.fields.files import ImageFieldFile, FileField class SampleForm(forms.ModelForm): img = forms.ImageField( required=False, widget=forms.ClearableFileInput(attrs={'class': 'form-control-file'}), label='画像' ) class Meta: model = Sample def __init__(self, *args, **kwargs): super(SampleForm, self).__init__(*args, **kwargs) if self.initial: self.fields['img'].initial = ImageFieldFile(instance=None, field=FileField(), name=self.instance.data.get('img', '')) <-- 画像のurlをimgに渡してあげる
因みにforms.ImageFieldのfieldを、モデルのfield名と同じ名称を使ってoverwriteしようとしたら、上手くいきませんでした。別名をちゃんと指定するようにしましょう。
意外と需要ありそうなのに、stackoverflowなどでもサンプルがなかなか見つからなく大変でした、、
結局、ImageFieldFileに行き着いた経緯としては、Adminの画像を扱うテンプレート側のwidgetの中身を見たことで、どういった型のものが受け渡されているのかを見て直ぐにImageFieldFileだということが分かったので、最初からこれに気付いていれば簡単な問題でした。。