跳转到主要内容

Django 标准化图像字段

项目描述

version codecov MIT License

Django 标准化图像字段

此包已被弃用,以支持django-pictures

迁移说明

首先,确保您理解这两个包之间的区别以及如何在现代Web应用程序中通过picture元素提供服务。

接下来,按照django-pictures的设置说明进行操作。

一旦设置完成,将您的模型更改为使用新的PictureField并提供您想要服务的aspect_ratios。但暂时不要创建迁移。

此步骤之后,应该更改您的模板和前端。新的占位符功能可以帮助您轻松完成此操作。

最后,运行makemigrations并将AlterField操作替换为AlterPictureField

我们强烈建议使用Django的image_widthimage_height字段,以避免不必要的I/O。如果您可以将这些字段添加到您的模型中,可以使用以下片段填充它们

import django.core.files.storage
from django.db import migrations, models
import pictures.models
from pictures.migrations import AlterPictureField

def forward(apps, schema_editor):
    for obj in apps.get_model("my-app.MyModel").objects.all().iterator():
        obj.image_width = obj.logo.width
        obj.image_height = obj.logo.height
        obj.save(update_fields=["image_height", "image_width"])

def backward(apps, schema_editor):
    apps.get_model("my-app.MyModel").objects.all().update(
        image_width=None,
        image_height=None,
    )

class Migration(migrations.Migration):
    dependencies = [
        ('my-app', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name="mymodel",
            name="image_height",
            field=models.PositiveIntegerField(editable=False, null=True),
        ),
        migrations.AddField(
            model_name="mymodel",
            name="image_width",
            field=models.PositiveIntegerField(editable=False, null=True),
        ),
        migrations.RunPython(forward, backward),
        AlterPictureField(
            model_name="mymodel",
            name="image",
            field=pictures.models.PictureField(
                aspect_ratios=["3/2", "3/1"],
                breakpoints={"desktop": 1024, "mobile": 576},
                container_width=1200,
                file_types=["WEBP"],
                grid_columns=12,
                height_field="image_height",
                pixel_densities=[1, 2],
                storage=django.core.files.storage.FileSystemStorage(),
                upload_to="pictures/",
                verbose_name="image",
                width_field="image_width",
            ),
        ),
    ]

我为什么想这样做?

这是一个Django ImageField的替代品,提供了一种标准化处理图片上传的方式。它设计得尽可能简单易用,并为所有图片字段提供一致的接口。它允许以不同尺寸变体(例如:缩略图、中等和高清版本)展示图片,并提供了一种处理过大图片的验证器。

功能

Django标准化图片字段实现了以下功能:

  • Django-Storages 兼容(例如:S3、Azure、Google Cloud Storage等)
  • 调整图片到不同的尺寸
  • 在模型级别访问缩略图,无需模板标签
  • 保留原始图片
  • 可以异步渲染(即作为一个 Celery任务
  • 限制可接受图片的尺寸
  • 将文件重命名为标准化的名称格式(使用可调用的 upload_to 函数,见下文)

安装

只需使用以下命令安装最新稳定版本:

pip install django-stdimage
# or
pipenv install django-stdimage

并将 'stdimage' 添加到你的 settings.py 中的 INSTALLED_APP,这样就完成了!

使用方法

现在安装完成后,你可以使用 StdImageFieldJPEGField

StdImageField 的使用与Django自带的 ImageField 类似,只不过你可以指定不同的尺寸变体。

JPEGFieldStdImageField 相同,但所有图片都将转换为JPEG格式,无论原始文件类型是什么。

变体

变体在字典中指定。键将引用调整大小的图片的属性。变体可以定义为元组或字典。

示例

from django.db import models
from stdimage import StdImageField, JPEGField


class MyModel(models.Model):
    # works just like django's ImageField
    image = StdImageField(upload_to='path/to/img')

    # creates a thumbnail resized to maximum size to fit a 100x75 area
    image = StdImageField(upload_to='path/to/img',
                          variations={'thumbnail': {'width': 100, 'height': 75}})

    # is the same as dictionary-style call
    image = StdImageField(upload_to='path/to/img', variations={'thumbnail': (100, 75)})

    # JPEGField variations are converted to JPEGs.
    jpeg = JPEGField(
        upload_to='path/to/img',
        variations={'full': (None, None), 'thumbnail': (100, 75)},
    )

    # creates a thumbnail resized to 100x100 croping if necessary
    image = StdImageField(upload_to='path/to/img', variations={
        'thumbnail': {"width": 100, "height": 100, "crop": True}
    })

    ## Full ammo here. Please note all the definitions below are equal
    image = StdImageField(upload_to='path/to/img', blank=True, variations={
        'large': (600, 400),
        'thumbnail': (100, 100, True),
        'medium': (300, 200),
    }, delete_orphans=True)

要在模板中使用这些变体,请使用 myimagefield.variation_name

示例

<a href="{{ object.myimage.url }}"><img alt="" src="{{ object.myimage.thumbnail.url }}"/></a>

上传到函数

你可以使用一个函数作为 upload_to 参数。使用 [Django Dynamic Filenames][dynamic_filenames].[dynamic_filenames]: https://github.com/codingjoe/django-dynamic-filenames

这允许根据模型实例给图片分配唯一的路径和文件名。

示例

from django.db import models
from stdimage import StdImageField
from dynamic_filenames import FilePattern

upload_to_pattern = FilePattern(
    filename_pattern='my_model/{app_label:.25}/{model_name:.30}/{uuid:base32}{ext}',
)


class MyModel(models.Model):
    # works just like django's ImageField
    image = StdImageField(upload_to=upload_to_pattern)

验证器

StdImageField 默认不实现任何尺寸验证。但是,可以通过验证器属性和随此包一起提供的验证器集合来指定验证。验证器可用于表单和模型。

示例

from django.db import models
from stdimage.validators import MinSizeValidator, MaxSizeValidator
from stdimage.models import StdImageField


class MyClass(models.Model):
    image1 = StdImageField(validators=[MinSizeValidator(800, 600)])
    image2 = StdImageField(validators=[MaxSizeValidator(1028, 768)])

注意:应谨慎使用 MaxSizeValidator。由于存储并不昂贵,你不应该限制上传尺寸。如果你想防止用户耗尽你的内存,你应该限制HTTP上传体的尺寸。

删除图片

Django 从版本 1.3 开始不再支持自动删除。

从版本 5 开始,此包支持 delete_orphans 参数。如果文件被删除或替换,且具有 StdImageField 的对象被删除,它将删除孤儿文件。如果字段值被更改或重新分配,它将不会删除文件。在这些罕见的情况下,你需要自己处理正确的删除。

from django.db import models
from stdimage.models import StdImageField


class MyModel(models.Model):
    image = StdImageField(
        upload_to='path/to/files',
        variations={'thumbnail': (100, 75)},
        delete_orphans=True,
        blank=True,
    )

异步图片处理

如celery之类的工具允许在请求外执行耗时的任务。如果你不想等待请求中变体的渲染,StdImage为你提供了传递异步关键字和一个触发异步任务的 'render_variations' 函数的选项。请注意,回调不是事务保存,但文件变体会存在。以下示例基于celery。

tasks.py:

from django.apps import apps

from celery import shared_task

from stdimage.utils import render_variations


@shared_task
def process_photo_image(file_name, variations, storage):
    render_variations(file_name, variations, replace=True, storage=storage)
    obj = apps.get_model('myapp', 'Photo').objects.get(image=file_name)
    obj.processed = True
    obj.save()

models.py:

from django.db import models
from stdimage.models import StdImageField

from .tasks import process_photo_image

def image_processor(file_name, variations, storage):
    process_photo_image.delay(file_name, variations, storage)
    return False  # prevent default rendering

class AsyncImageModel(models.Model):
    image = StdImageField(
        # above task definition can only handle one model object per image filename
        upload_to='path/to/file/', # or use a function
        render_variations=image_processor  # pass boolean or callable
    )
    processed = models.BooleanField(default=False)  # flag that could be used for view querysets

重新渲染变体

你可能已经向现有字段添加或更改了变体。这意味着你需要渲染新的变体。这可以通过管理命令来完成。

python manage.py rendervariations 'app_name.model_name.field_name' [--replace] [-i/--ignore-missing]

“replace”选项将替换所有现有文件。 “ignore-missing”选项将暂停“缺少源文件”错误并继续渲染其他文件的变体。否则,命令将在遇到第一个缺少的文件时停止。

项目详情


发布历史 发布通知 | RSS订阅

下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分布

django-stdimage-6.0.2.tar.gz (15.0 kB 查看哈希值)

上传时间 源代码

构建分布

django_stdimage-6.0.2-py2.py3-none-any.whl (19.3 kB 查看哈希值)

上传时间 Python 2 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面