Python中如何实现Django后台上传图片并生成部分区域缩略图在前台展示?

尺寸是固定的


Python中如何实现Django后台上传图片并生成部分区域缩略图在前台展示?
9 回复

各大云存储不都支持图片裁剪缩略吗?


# settings.py 配置
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# models.py
from django.db import models
from PIL import Image
import os

class Article(models.Model):
    title = models.CharField(max_length=100)
    original_image = models.ImageField(upload_to='originals/')
    thumbnail = models.ImageField(upload_to='thumbnails/', blank=True)
    crop_x = models.IntegerField(default=0)
    crop_y = models.IntegerField(default=0)
    crop_width = models.IntegerField(default=100)
    crop_height = models.IntegerField(default=100)
    
    def generate_thumbnail(self):
        if not self.original_image:
            return
        
        # 打开原始图片
        img = Image.open(self.original_image.path)
        
        # 确保裁剪区域在图片范围内
        width, height = img.size
        x = min(max(self.crop_x, 0), width - 1)
        y = min(max(self.crop_y, 0), height - 1)
        crop_w = min(self.crop_width, width - x)
        crop_h = min(self.crop_height, height - y)
        
        # 裁剪指定区域
        cropped = img.crop((x, y, x + crop_w, y + crop_h))
        
        # 生成缩略图(固定为100x100)
        cropped.thumbnail((100, 100))
        
        # 保存缩略图
        thumb_path = f'thumbnails/{os.path.basename(self.original_image.name)}'
        full_path = os.path.join(settings.MEDIA_ROOT, thumb_path)
        cropped.save(full_path)
        
        # 更新模型字段
        self.thumbnail.name = thumb_path
        self.save()

# admin.py
from django.contrib import admin
from .models import Article

class ArticleAdmin(admin.ModelAdmin):
    list_display = ['title', 'original_image', 'thumbnail']
    readonly_fields = ['thumbnail_preview']
    
    def thumbnail_preview(self, obj):
        if obj.thumbnail:
            return format_html('<img src="{}" width="100" height="100" />', obj.thumbnail.url)
        return "No thumbnail"
    thumbnail_preview.short_description = 'Thumbnail Preview'
    
    def save_model(self, request, obj, form, change):
        super().save_model(request, obj, form, change)
        obj.generate_thumbnail()

admin.site.register(Article, ArticleAdmin)

# template展示
"""
{% for article in articles %}
    <div>
        <h3>{{ article.title }}</h3>
        <p>Original: <img src="{{ article.original_image.url }}" width="300"></p>
        <p>Thumbnail: <img src="{{ article.thumbnail.url }}" width="100" height="100"></p>
    </div>
{% endfor %}
"""

# views.py
from django.shortcuts import render
from .models import Article

def article_list(request):
    articles = Article.objects.all()
    return render(request, 'articles/list.html', {'articles': articles})

核心就这几步:1)用PIL的crop()裁剪指定区域;2)用thumbnail()调整尺寸;3)保存到media目录。记得安装Pillow库,配置好MEDIA设置。

建议用Pillow处理图片裁剪。

solr-thumbnail

印象中好像在 model 里可以定义 upload 图片之后做什么操作,也可能是别的地方

如果你问的是,如何自动选取最佳的一部分做缩略图,那这问题还有讨论的看头。

先说明,我对此没有经验。

最佳一般都在图片中间区域

我指的那种通过 CV 手段计算出图片最佳区域的。

https://blog.algorithmia.com/smart-thumbnail-image-cropping/

thum_width = models.PositiveIntegerField(default=50,verbose_name=‘缩略图宽度’)
thum_height = models.PositiveIntegerField(default=50,verbose_name=‘缩略图高度’)
img_thum = models.ImageField(upload_to=ThumPathAndRename(“product/thum/”),width_field=‘thum_width’,
height_field=‘thum_height’,null=True,blank=True,editable=True,verbose_name=‘缩略图’)

这样可以控制高度和宽度,代码很丑,可以改 CSS 呀

回到顶部