validators for bulk image upload
I have a feature that allows users to upload multiple images. I want to setup a validator to only allow images that are under 3MB.
def validate_image_bulk(images):
file_size = images.file.size
if file_size > settings.MAX_UPLOAD_SIZE:
raise ValidationError(f'Cover Image {images} is too large 3mb max')
How can I get a list of the images being uploaded and validate them at the same time. In a view I could do something like request.FILES.getlist('images')
is there something similar like this?
Solution 1:
Things to understand
-
images
invalidate_image_bulk
is a single file (that's whatmodels.ImageField
handles and that's why you doimages.file.size
same asimage.file.size
invalidate_image
). -
validate_image_bulk
is always called with the same file (specifically, the last file) fromPostImagesForm(request.POST, request.FILES)
. -
for x in images
invalidate_images_bulk
loops over the bytes, not multiple images.
Solution
Do PostImagesForm(request.POST, {'images': image})
instead:
post_images_forms = []
for image in request.FILES.getlist('images'):
post_images_form = PostImagesForm(request.POST, {'images': image})
if not post_images_form.is_valid():
break
post_images_forms.append(post_images_form)
else: # if len(post_images_forms) == len(request.FILES.getlist('images')):
for post_images_form in post_images_forms:
instance = post_images_form.save(commit=False)
instance.post_id = PostFormID.id
instance.save()
Recommendations for sanity
- Rename
images
toimage
. - Discard
validate_images_bulk
since it's functionally same asvalidate_image
.
class PostImages(models.Model):
# images = models.ImageField(validators=[validate_image_bulk]) # Change this
image = models.ImageField(validators=[validate_image]) # to this
Solution 2:
crate an validator.py inside your app:
validator.py
from django.core.exceptions import ValidationError
def validate_file_size(value):
filesize = value.size
if filesize > 3145728: #3 * 1024 * 1024
raise ValidationError('The maximum file size that can be uploaded is 3MB')
else:
return value
your models.py
from .validator import *
from django.core.validators import FileExtensionValidator #if you also want to use file type Validator
class mymodel(models.Model)
image = models.ImageField(upload_to='blog/images/',validators=[validate_file_size,FileExtensionValidator( ['png','jpg'] )],blank=True,null=True) #only accept 'png' and 'jpg' image.
You can check django documentation for FileExtensionValidator