djangoで画像のアップロード機能を実装したけど、バリデーション(妥当性チェック)をデフォルト以外でも設定したい時の解決方法(コード)を紹介します。
また以前紹介しました、django画像アップロード機能を実装する方法の追加実装にもなっています。
・djangoの画像アップロードにバリデーションをかけたい
・OS : Mac
・django 2.2
・python 3.8
それでは順番に説明をしていきます。
コンテンツ
なぜバリデーションを行うのか
画像をアップロードすべき場所に動画や画像ファイル(jpeg,png)以外のものをアップロードされるとセキュリティ上宜しくありません。
また重たいデータ(例えば40MB)画像であったり、横幅が4,000pxを超えるような暴力的な画像幅をきちんと投稿(POST)する前に、バリデーションをかけてあげないとサーバー側の負荷は甚大です。
djangoのデフォルト装備
上記で説明しましたが、django2系以降だとアップロード画面でそもそも画像以外のファイルはアップロードファイルとして選択できないようになっています。
「ファイルを選択」すると・・・
ちなみにmp4の動画は選択できるのですが、postを実行しようとすると下記バリデーションがかかります。
(※.errorlistのCSSを個別に設定しております)
実装前に他のSNSを確認
今回は、プロフィール画像をアップロードするという前提で話を進めますので、FACEBOOKを例に実際はどのような制約をかけているのか調べてみます。
・180×180ピクセルが必要 => それ以上のサイズの場合や正方形ではない場合、正方形にトリミングされます。
ちなみにFacebook以外のTwitterでもアイコン設定時にはきちんとサイズ指定がされています。
今回はバリデーションのみの紹介になりますので、exif処理やリサイズ、ファイル名のハッシュ化等はまた別の機会に行います。
コードの紹介
コードはformsに書きます。
views側に書く人もいますが、djangoのそもそもの概念通りにフォームに記述します。
・ユーザーの入力データの保持
・入力データのバリデーションチェック及び、妥当性検証済みのデータやエラーメッセージ保持
そして今回は以下の画像データに対してバリデーションをかけてアップロードできないように以下の3つのバリデーションをかけます。
1.ファイルフォーマットが画像以外のものはアップロードできない
2.縦横幅が200px×200px以下のものはアップロードできない
3.20MB以上の画像ファイルはアップロードできない
実際のコードです。
forms.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
from django import forms from PIL import Image class UpLoadProfileImgForm(forms.Form): avator = forms.ImageField(required=True) def clean_avator(self): ''' 1. file format 2. Vertical and horizontal 3. file size ''' avator = self.cleaned_data['avator'] if not avator: raise ValidationError('投稿されたデータが画像ではありません') IMG_WIDTH = 200 if avator.image.width < IMG_WIDTH: raise ValidationError( 'この画像の横幅は%spxです。%spx以上の横幅の画像の登録をお願いします' \ % (avator.image.width, IMG_WIDTH) ) IMG_HEIGHT = 200 if avator.image.height < IMG_HEIGHT: raise ValidationError( 'この画像の高さは%spxです。%spx以上の高さの画像の登録をお願いします' \ % (avator.image.width, IMG_HEIGHT) ) IMG_SIZE = 2*1000*1000 if avator.size > IMG_SIZE: raise ValidationError( '画像サイズが大きすぎます。%sMBより小さいサイズの画像をお願いします。' \ % str(IMG_SIZE//1000//1000) ) return avator |
これで完了しました。
テスト
こちらが本当に機能するかの動作テストをします。
横幅が小さい(20px)の画像
試しに横幅が20pxの画像をアップロードしてみます。
ファイルサイズの大きな画像
試しにファイルサイズ(43MB)の大きな画像をアップロードしてみます。
テストも問題ないですね。以上になります。
スクールを利用して本格的に学ぶ
いかがでしたでしょうか?
10人中9人が挫折すると言われるプログラミングを、ヒロヤンも実はプログラミングスクールで学習をしてきたからで、結果、今はPythonエンジニアとして働いています。
挫折率が高いプログラミングこそお金を払ってメンターを付けて、道を見失わないように環境を構築する必要があるのではないでしょうか。
これはダイエットで自分一人では痩せられないけど、トレーナーを付けて否が応でもせざるを得ない環境を作ると一緒ですね。
ヒロヤンもプログラミング勉強開始直後はあれこれ悩みましたが、悩むよりも手っ取り早くスクールに登録した方が最短ルートで勉強できるのではないかと考え、結果挫折せずに今に至っています。
今なら無料でキャリアカウンセリングを行っているTechAcademyのようなプログラミングスクールもありますのでこれを機会に是非カウンセリングだけでも受けてみてはいかがでしょうか?
上記リンク先から無料相談ができます。
またこちら(↓)ではPython専用のプログラミングスクールをまとめ紹介しています。
コメントを残す