[Django] FileFieldのファイルサイズをチェックするFormsのValidation

 DjangoのFormsのバリデーションには拡張子チェックなどはありますがファイルサイズをチェックするバリデーションがありません。

 ここは自前で実装する必要があります。

自前でFormのValidatorを実装するには


 自前といっても、__call__メソッドオーバーライドして関数オブジェクトっぽく動くようにして、バリデーションチェックが通らなければValidationErrorをraiseするという単純なものです。

 __call__は設定された値、FileFieldであればファイルの値(UploadedFile型)の値を受け取って、その値をチェックして問題あればValidationErrrorをraiseします。

 Formのバリデーションチェックで関数オブジェクトとして呼び出され、ValidationErrorをraiseだけしておけば、forms側でexceptしてエラーメッセージとか色々設定してくれるっぽい。

実装・サンプルコード


 ファイルサイズチェックのValidatorは以下のような感じです。

 UploadedFileはUploadedFile#sizeでファイルのバイト数を取得できるようになっています。

 あとはその値を利用するだけです。

from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import UploadedFile

class FileSizeValidator:
    def __init__(self, val: float, byte_type="mb"):
        assert byte_type in ["b", "kb", "mb", "gb"]
        if byte_type == "b":
            self._upper_byte_size = val
        elif byte_type == "kb":
            self._upper_byte_size = 1000 * val
        elif byte_type == "mb":
            self._upper_byte_size = (1000 ** 2) * val
        elif byte_type == "gb":
            self._upper_byte_size = (1000 ** 3) * val
        self._err_message = f"アップロードファイルは{val}{byte_type.upper()}未満にしてください."

    def __call__(self, file_val: UploadedFile):
        byte_size = file_val.size
        if byte_size > self._upper_byte_size:
            raise ValidationError(message=self._err_message)

 使い方はこんな感じです。formsのフィールドのvalidatorsに指定できます。

 指定した容量以上のファイルをアップロードするとform.file.errorsにエラーメッセージが表示されます。

from django import forms

class FileUploadForm(forms.Form):
    file = forms.FileField(
        validators=[FileSizeValidator(val=1, byte_type="gb")],
        required=False,
    )

 アップロードされたファイルをdjango.modelsのFileField/ImageFieldとしてDB保存していくと思いますが、更新・削除時にDB上では削除されているけど実際にファイルは削除されません。

 django.modelsのFileField/ImageFieldのファイルを、更新・削除時に自動削除する方法については別記事でまとめていますので、よかったらそちらも見てみてください!

コメントを残す

メールアドレスが公開されることはありません。