You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Admin中上传图片前检查图片宽高?

How to Add Image Aspect Ratio Validation in Django Admin for Banner Model

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

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_RATIO to match your needs (e.g., 1.0 for square images, 9/16 for portrait).
  • The TOLERANCE value 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:48:13