画像登録
settings
画像などのファイルを保存するフォルダを登録する。
/media
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'
urls
MEDIA フォルダのパスをプロジェクトのurls.pyのurlpatternsにプラスして登録。
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
models
クラスにフィールドを登録
picture = models.ImageField(upload_to='img/',blank=True, null=True, verbose_name='イメージ')
upload_toで保存フォルダを指定するがmedia/imgに保存したいので、img/と登録する。
(mediaは基本フォルダとして登録済み)
forms
forms.py内のclassに登録(更新)のフォームの項目を登録しておく
DjangoはViewでこれを呼び出してTemplateに渡すだけで簡単に登録フォームが作成される。
画像のファイル選択機能やファイルのクリア機能も自動で用意される。
class DateInput(forms.DateInput):
input_type = 'date'
class PageForm(ModelForm):
class Meta:
model = Page
fields =["title","body","page_date", "picture"]
widgets = {
'page_date': DateInput(),
}
DateInputは日付項目の入力を楽にするwidgetsを使うため。
widgets に項目とinput_typeの辞書を渡すだけでwidgetが使えるようだ。(不思議)
views
CreateViewを使用して簡単に済ますが、先ほどのformsのclassをTemplateに伝える。(更新時も同様)
class PageCreateView(CreateView):
model = models.Page
template_name = 'diary/diary_create.html'
form_class=PageForm
success_url=reverse_lazy('diary:index')
template
FormのPOSTで登録するが、
<form method="POST" enctype="multipart/form-data">
の enctypeを忘れないように。
画像表示
template
ImageFieldとして登録してあるので、Views.pyから受け取るレコードのインスタンスをdiaryとすると、
diary.picture.url でパスを取得できるので、これをimgのsrcに指定すればよい。
<img class="mw20" src="{{ diary.picture.url }}" />
画像更新
views
UpdateViewを使う場合の書き方がわからないので、Viewを利用。
保存前に画像のパスを保持。
保存後に画像のパスを取得。
保存前と保存後に画像のパスが異なるか保存後に画像がない場合、保存前のパスのファイルを削除する。
basename=""
if diary.picture:
picture = diary.picture
basename = Path(picture.path)
if form.is_valid():
form.save()
paper2 = get_object_or_404(Page, pk=pk)
if basename !="":
if paper2.picture:
picture2=paper2.picture
basename2=Path(picture2.path)
if basename != basename2:
basename.unlink(missing_ok=True)
else:
basename.unlink(missing_ok=True)
画像削除
models
データ削除時に、対象クラスの画像を削除する関数をオーバーライドしておく。
これでDeleteViewを使用して簡単にデータ削除を実装できる。
def delete(self, *args, **kwargs):
picture = self.picture
super().delete(*args, **kwargs)
if picture:
Path(picture.path).unlink(missing_ok=True)