59
models.py
class Product(models.Model):
image = models.ImageField(upload_to="/a/b/c/")
forms.py
class ProductForm(forms.ModelForm):
# Add some custom validation to our image field
def clean_image(self):
image = self.cleaned_data.get('image', False)
if image:
if image._size > 4*1024*1024:
raise ValidationError("Image file too large ( > 4mb )")
return image
else:
raise ValidationError("Couldn't read uploaded image")
56
Essentially this is a duplicate of Django File upload size limit
You have two options:
-
Use validation in Django to check the uploaded file’s size. The problem with this approach is that the file must be uploaded completely before it is validated. This means that if someone uploads a 1TB file, you’ll probably run out of hard drive space before the user gets a form error.
-
Configure the Web server to limit the allowed upload body size. e.g. if using Apache, set the
LimitRequestBody
setting. This will mean if a user tries to upload too much, they’ll get an error page configurable in Apache
As @pastylegs says in the comments, using a combination of both is probably the best approach. Say you want a maximum of 5MB, perhaps enforce a 20MB limit at the Web server level, and the 5MB limit at the Django level. The 20MB limit would provide some protection against malicious users, while the 5MB limit in Django provides good UX.
- [Django]-Best way to write an image to a Django HttpResponse()
- [Django]-Why do we need to use rabbitmq
- [Django]-Can't install via pip because of egg_info error
29
Here is another option that I didn’t see across the variations of this question on stackoverflow: use a custom validator in your models. If you use this technique and a ModelForm in forms.py, then this should be all you need.
models.py
from django.core.exceptions import ValidationError
class Product(models.Model):
def validate_image(fieldfile_obj):
filesize = fieldfile_obj.file.size
megabyte_limit = 5.0
if filesize > megabyte_limit*1024*1024:
raise ValidationError("Max file size is %sMB" % str(megabyte_limit))
image = models.ImageField(upload_to="/a/b/c/", validators=[validate_image])
- [Django]-In Django models.py, what's the difference between default, null, and blank?
- [Django]-Unable to import path from django.urls
- [Django]-Does SQLAlchemy have an equivalent of Django's get_or_create?