在将图片上传到Django时,字段width的值为NULL,违反了非空约束

后端开发 2026-07-08

我正在使用Django==5.2.12和 django-imagekit==6.1.0

这是我的PostImage模型:

class PostImage(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True, related_name="images")
    image = ProcessedImageField(verbose_name=_("image"), storage=post_image_storage, upload_to=upload_to_post_image_directory, width_field="width", height_field="height", blank=False, null=True, format="JPEG", options={"quality": 100}, processors=[ResizeToFit(width=1024, upscale=False)])
    width = models.PositiveIntegerField(editable=False, null=False, blank=False)
    height = models.PositiveIntegerField(editable=False, null=False, blank=False)
    hash = models.CharField(_("hash"), max_length=64, blank=False, null=True)
    thumbnail = ProcessedImageField(verbose_name=_("thumbnail"), storage=post_image_storage, upload_to=upload_to_post_image_directory, blank=False, null=True, format="JPEG", options={"quality": 50}, processors=[ResizeToFit(width=1024, upscale=False)])
    media = GenericRelation(PostMedia)
    image_view_type = (
        ("regularimage", "regularimage"),
        ("gridimages", "gridimages"),
    viewtype = models.CharField(max_length=24, choices=image_view_type, default="")

在创建PostImage对象时,抛出了这个错误。

列 "width" 的空值违反了非空约束。

由于我需要将width和 height字段用于后续处理来计算

我不想把width和 height字段设为null=True。不过,为了验证效果,我确实尝试了指定null=True。结果PostImage对象确实被创建,但width和 height没有任何数值。

详细追踪:

 django.db.utils.IntegrityError: null value in column "width" of relation "myapi_posts_postimage" violates not-null constraint
my-api-webserver-0  | DETAIL:  Failing row contains (1, posts/9957dc49-639b-490e-87f5-54cab35c0229/582a8f62-86d5-4c3d-a1..., null, null, 01d2d1ce86aa7007f1cecad2259394163b95987a850e6c2d6a48c322a2dc8df0, posts/9957dc49-639b-490e-87f5-54cab35c0229/33d944aa-ded1-49cb-a9..., regularimage, 1).

解决方案

这个错误表明你的数据库中存在width列为NULL的现有记录。

很可能你修改了模型,使width字段变为非空。运行Django服务器时,width字段的现有NULL值会触发错误,因为字段的状态已从可空改为不可空。

如何修复?

要么设置一个默认值来填充数据库中现有的NULL列,要么使用以下命令清空数据库中的现有记录:

python manage.py flush

备选方案

我只是试图创建 PostImage 对象,然后先创建一个类似于 post_image = cls.objects.create(image =file) 的PostImage,再像 image_width=post_image.width 那样提取值。 - Earthling

你正在创建一个 PostImage 对象,但没有为 width(以及后续的 height 等)指定值。Django不会自动把这当作图片的宽度/高度。你需要自己填充。比如可以这样:

class PostImage(models.Model):
    # ...

    def save(self, *args, **kwargs):
        image = self.image
        if image:
            self.width = image.width
            self.height = image.height
            # ...
        super().save(*args, **kwargs)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章