Python 2.7.13
Django==1.19.5
pillow==4.2.1
续前篇:Django 的图片上传与显示 1: FileField 方法
上次使用了 FileField,这里讲使用 ImageField 来实现
0 ImageField 依赖包 pillow 安装
$ pip install -i https://pypi.douban.com/simple pillow
1 修改 models
其中 ImageField 在获得图片以后,会用 pillow 包去获取图片的高和宽这两个属性(以及其他属性),另外设定 IntegerField height_field
和 width_field
用于存放的大小。
class Post(models.Model):
image = models.ImageField(null=True, blank=True,
height_field="height_field",
width_field="width_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
修改 models 之后,makemigrations/migrate常规操作。
2 测试
和 FileField 的使用情况一样。另外在 admin 中可以看见详情中出现了 Height field 和 Width field 属性。
3 存放目录设置
posts/models.py
设置一个辅助函数(helper function),每次保存图片的时候,都存在以 id 为目录中。
def upload_location(instance, filename):
return "{0}/{1}".format(instance.id, filename)
class Post(models.Model):
image = models.ImageField(upload_to=upload_location,
null=True, blank=True,
height_field="height_field",
width_field="width_field")
# ...
- 当然
upload_to=
可以硬编码成upload_to="/media/xxx"
,但是辅助函数方式的代码更健壮。 -
upload_location
可以使用 instance 的其他属性,比如存在 user 字段(field),则可以使用instance.user
。 - 修改字段(Field)的参数不用做 migrate。修改 Field 的名字和类型才需要 migrate。
- 最后就存放在了
/media_cdn/23/filename.png
。
另一种存放文件名
这里拿到文件名 filename 以后,根据 .
进行 split 获得后缀名。后面存放名字的时候,不使用上传文件名,而是设定为 id 作为文件名,最后再把后缀名拼接字符串上去。
def upload_location(instance, filename):
filebase, extension = filename.split(".")
return "{0}/{0}.{1}".format(instance.id, extension)
但是这里文件名中也可能存在多个 .
,所以在 split 以后的 list 中,只获取最后一个字符型元素作为文件后缀名。
def upload_location(instance, filename):
extension = filename.split(".")[-1]
return "{0}/{0}.{1}".format(instance.id, extension)