如何在Django Admin面板的图片字段中实现客户端图片大小限制?
解决Django Admin内联图片字段前端文件大小限制问题
要在用户选择图片时就检测文件大小,避免提交大文件触发DATA_UPLOAD_MAX_MEMORY_SIZE异常,核心是前端实时拦截+后端双重验证,具体实现步骤如下:
一、自定义内联类,添加前端检测脚本
修改你的MenuImageInline(若原内联类为默认实现),通过Media类引入自定义JS脚本,在前端监听文件选择事件:
from django.contrib import admin from .models import MenuImage class MenuImageInline(admin.TabularInline): model = MenuImage extra = 1 # 根据需求调整默认显示的内联数量 class Media: js = ('admin/js/image_size_check.js',) # 自定义JS文件路径,需放在项目static/admin/js目录下
在static/admin/js/目录下创建image_size_check.js,写入以下代码(示例限制单张图片不超过5MB,可按需修改MAX_FILE_SIZE):
document.addEventListener('DOMContentLoaded', function() { // 监听所有内联图片字段的文件选择器 const fileInputs = document.querySelectorAll('input[type="file"][name*="menu_images"][name*="image"]'); const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB,单位字节 const ERROR_MSG = `图片大小不能超过${MAX_FILE_SIZE/(1024*1024)}MB`; fileInputs.forEach(input => { input.addEventListener('change', function(e) { const file = this.files[0]; if (file && file.size > MAX_FILE_SIZE) { alert(ERROR_MSG); // 清空文件选择 this.value = ''; // 移除Admin自动生成的预览图(如果存在) const preview = this.closest('.file-upload').querySelector('.thumbnail'); if (preview) preview.remove(); } }); }); });
二、后端添加文件大小验证(防止前端绕过)
在MenuImage模型的ImageField上添加验证器,同时在clean方法中补充检查,确保后端也能拦截大文件:
from django.core.validators import FileExtensionValidator, MaxFileSizeValidator from django.core.exceptions import ValidationError class MenuImage(models.Model): """Salon Image Model""" class Meta: verbose_name = _("Menu Image") verbose_name_plural = _("Menu Images") salon = models.ForeignKey( Salon, on_delete=models.CASCADE, related_name='menu_images', null=True, blank=True) image = models.ImageField( upload_to='salon_images', help_text="Dimensions should in 175 x 100 px", validators=[ FileExtensionValidator(['jpg', 'jpeg', 'png']), MaxFileSizeValidator(5 * 1024 * 1024) # 和前端限制保持一致,单位字节 ] ) def __str__(self): return self.salon.full_name def clean(self): super().clean() # 额外检查文件大小,避免验证器未触发的边界情况 if self.image: if self.image.size > 5 * 1024 * 1024: raise ValidationError({"image": "图片大小不能超过5MB"}) def save(self, *args, **kwargs): compressed_image = ImageResizing.custom_resizing_and_compress(self.image) self.image = compressed_image super().save(*args, **kwargs)
三、关于DATA_UPLOAD_MAX_MEMORY_SIZE的补充说明
当前设置的DATA_UPLOAD_MAX_MEMORY_SIZE约为9.5MB,若多个内联字段同时上传,总大小可能超出该值。但通过前端拦截单张图片大小后,总上传量会被控制在合理范围,无需过度调大该参数,避免增加服务器内存压力。
内容的提问来源于stack exchange,提问作者Hassan Shahzad
相关产品推荐
相关产品推荐

