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

Django Admin保存前处理上传图片:获取文件、校验与查重

Fixing Your Django Image Upload Model

Hey there! Let's get your UploadedImage model working correctly. The main issue you're facing is trying to access request.FILES directly in the model's save method—models don't have access to the request object, so we need to use the self.image field itself to get the uploaded file. Here's how to fix and improve your code:

Key Issues to Address

  1. Accessing the Uploaded File: Use self.image.file instead of request.FILES['image']—this gives you the actual file object attached to the ImageField.
  2. MD5 Hash Generation: You need to read the file's binary content, but remember to reset the file pointer after reading so PIL can open it later.
  3. Duplicate Check: Your hash_exists static method was using incorrect syntax—exists() doesn't take keyword arguments; use filter() first.
  4. Safe ID Generation: Your generate_name method would fail on the first upload (since there are no existing IDs), so we'll add a fallback for that case.
  5. Proper Error Handling: Use Django's ValidationError instead of a generic ValueError so the Admin interface displays the error to the user properly.

Updated Model Code

from django.db import models
from django.core.exceptions import ValidationError
from hashlib import md5
from PIL import Image
import os

class UploadedImage(models.Model):
    """Model for uploaded images with metadata and duplicate detection"""
    name = models.CharField(max_length=255, default='')
    pub_date = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='images/')
    height = models.IntegerField(default=0)
    width = models.IntegerField(default=0)
    extension = models.CharField(max_length=20, null=False, default='')
    hash = models.CharField(max_length=32, null=False, unique=True, db_column='hash', default='')

    def __str__(self):
        return self.name

    @staticmethod
    def hash_exists(image_hash):
        # Correct syntax for checking existence
        return UploadedImage.objects.filter(hash=image_hash).exists()

    def generate_name(self):
        # Handle first upload case when no IDs exist yet
        latest_img = UploadedImage.objects.values('id').order_by('-id').first()
        if latest_img:
            img_id = latest_img['id'] + 1
        else:
            img_id = 1
        self.name = f"{img_id}_{self.hash[-4:]}"

    def save(self, *args, **kwargs):
        # Only process if a new image was uploaded (or updated)
        if self.image and not self.hash:  # Skip if hash already exists (for updates)
            # Read the file content and reset the pointer
            file_content = self.image.file.read()
            self.image.file.seek(0)  # Reset so PIL can read it

            # Generate MD5 hash
            self.hash = md5(file_content).hexdigest()

            # Check for duplicates
            if UploadedImage.hash_exists(self.hash):
                raise ValidationError("This image has already been uploaded (duplicate detected).")

            # Get image dimensions and format
            with Image.open(self.image.file) as img:
                self.width, self.height = img.size
                # Get extension from image format or file name
                self.extension = img.format.lower() if img.format else os.path.splitext(self.image.name)[1].lstrip('.').lower()

            # Generate a unique name
            self.generate_name()

        # Call the parent save method
        super().save(*args, **kwargs)

Explanation of Key Changes

  • File Access: self.image.file gives us the uploaded file object. We read its content for the hash, then call seek(0) to reset the file pointer—this is crucial because reading the file moves the pointer to the end, and PIL would fail to open an empty file otherwise.
  • Duplicate Check: Using filter(hash=image_hash).exists() is the correct way to check if a hash already exists in the database.
  • Error Handling: Raising ValidationError ensures that the Django Admin will display the error message to the user instead of just printing it to the console.
  • Extension Handling: Fallback to the file name's extension in case PIL can't detect the image format (edge case for rare formats).
  • ID Generation: Added a fallback for the first upload when there are no existing records, so img_id defaults to 1 instead of throwing an error.

Notes for Usage

  • Make sure you have Pillow installed (you mentioned it's imported, so you probably do, but double-check with pip install pillow).
  • When updating an existing UploadedImage instance without changing the image, the hash check and metadata generation will be skipped (since self.hash already exists).
  • The hash field is set to max_length=32 because MD5 hashes are exactly 32 characters long—no need for 50.

内容的提问来源于stack exchange,提问作者user3605780

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:12:53