如何在Django Admin中上传图片前检查图片宽高?
To validate the aspect ratio of images before uploading in your Django Admin, you have two main approaches—model-level validation (runs everywhere the model is saved) or admin form-level validation (only applies to the admin interface). Here's how to implement both:
Prerequisite: Install Pillow
First, you need the Pillow library to process image dimensions. Install it via pip:
pip install pillow
Approach 1: Model-Level Validation (Recommended)
This method ensures the aspect ratio check runs whenever the Banner model is saved—whether via admin, API, or any other form. Modify your Banner model to add a clean() method:
from django.db import models from django.core.exceptions import ValidationError from PIL import Image from django.utils.translation import gettext_lazy as _ class Banner(models.Model): image = models.ImageField( _('Image'), upload_to=upload_path, blank=True, null=True, content_types=['image/jpg', 'image/jpeg', 'image/png'], max_size=1 * 1024 * 1024, extensions=['jpg', 'jpeg', 'png'] ) type_of_banner = models.CharField(_('Type of Banner'), max_length=3, default='web') class Meta: verbose_name = _('Banner') verbose_name_plural = _('Banners') def __str__(self): return '%s' % str(self.id) def clean(self): super().clean() # Only validate if an image is provided if self.image: try: # Open the uploaded image to get dimensions with Image.open(self.image) as img: width, height = img.size # Define your required aspect ratio (adjust to your needs) REQUIRED_ASPECT_RATIO = 16 / 9 # Example: 16:9 landscape # Allow a small tolerance to account for minor pixel differences TOLERANCE = 0.01 current_ratio = width / height # Check if the ratio is within acceptable range if abs(current_ratio - REQUIRED_ASPECT_RATIO) > TOLERANCE: raise ValidationError({ 'image': _( "Image must have an aspect ratio of 16:9. " "Current dimensions are %(width)dx%(height)d (ratio: %(ratio).2f:1)." ) % { 'width': width, 'height': height, 'ratio': current_ratio } }) except Exception as e: # Handle invalid image files raise ValidationError({ 'image': _("Invalid image file: %(error)s") % {'error': str(e)} })
Why this works:
- The
clean()method is called automatically before the model is saved, so invalid images are rejected before being stored on the server. - This validation applies to all instances of the Banner model, not just those created via admin.
Approach 2: Admin Form-Level Validation
If you only want the aspect ratio check to apply in the Admin interface (and not elsewhere like APIs), create a custom ModelForm for your BannerAdmin:
from django.contrib import admin from django import forms from django.core.exceptions import ValidationError from PIL import Image from django.utils.translation import gettext_lazy as _ from .models import Banner class BannerAdminForm(forms.ModelForm): class Meta: model = Banner fields = ('image', 'type_of_banner') def clean_image(self): image = self.cleaned_data.get('image') if image: try: with Image.open(image) as img: width, height = img.size REQUIRED_ASPECT_RATIO = 16 / 9 # Adjust to your needs TOLERANCE = 0.01 current_ratio = width / height if abs(current_ratio - REQUIRED_ASPECT_RATIO) > TOLERANCE: raise ValidationError( _( "Image must have an aspect ratio of 16:9. " "Current dimensions are %(width)dx%(height)d (ratio: %(ratio).2f:1)." ) % { 'width': width, 'height': height, 'ratio': current_ratio } ) except Exception as e: raise ValidationError(_("Invalid image file: %(error)s") % {'error': str(e)}) return image class BannerAdmin(admin.ModelAdmin): model = Banner form = BannerAdminForm # Attach the custom form fields = ('image', 'type_of_banner') list_display = ('image', 'type_of_banner') # Register the admin as before android_dashboard.register(Banner, BannerAdmin)
Key Notes:
- Adjust
REQUIRED_ASPECT_RATIOto match your needs (e.g.,1.0for square images,9/16for portrait). - The
TOLERANCEvalue prevents rejecting images with minor pixel differences (e.g., a 1600x901 image instead of 1600x900). - Both methods will display a clear error message in the Admin interface if the image doesn't meet the ratio requirement, before saving the file to the server.
内容的提问来源于stack exchange,提问作者Alireza

