写在前面
Django
本身用来开发已经很迅速了, 默认使用自带的 sqlite3
数据库, 可以完成基本的关系型数据存储的需求, 不过在其 model
中还有一个特别的字段, 就是 ImageField
, 顾名思义, 就是存储图片的一个字段
ImageField
虽然这个字段能够完成存储图片的功能, 但不代表这个字段的值, 就是一个图片, 一般使用它的 url
属性
一般是下面这样简单的用法:
- 在
project_name/settings.py
中写入:
1 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/') |
这样你就设定了一个 MEDIA_ROOT
, 这个目录是用来保存一些动态文件; 后面 ImageField
的图片会保存在这个目录下
- 设计你的
model
1 | Avatar = models.ImageField(upload_to = 'avatar') |
upload_to
表示你上传到哪个文件夹, 这个例子是上传到 /media/avatar
这里
- 在
view
中处理从前端提交的图片
这里其实就有很多中处理方法, 比如把图片视为简单的 python
file
, 然后自定义处理方式, 保存到自己想要的位置, 设定文件名等, 可以给一下实例代码:
1 |
|
不过这样有点重复造轮子的感觉, 毕竟 Django
设计了这个字段, 肯定有它的用法(当然需要高度自定义的话, 可能还是要自己造轮子)
其实最简单的方法就是把 取出来的 file
直接赋值给对应字段, 就像下面这样:
1 | t_user.Avatar = request.FILES['file'] |
这样这个字段就保存好这个图片的信息了, 如果你要使用这个图片的话, 可以使用它的 url
属性, 然后找到这个图片, 进行自定义处理
1 | # 在这里返回路径信息 |
其他细节
- 默认图片
因为这里本身的需求是对头像图片的处理, 所以要设定一张默认图片来显示, 其实也很简单, 在 model
里定义的时候添加 default
属性即可:
1 | Avatar = models.ImageField(upload_to = 'avatar', default = 'avatar/default.jpg') |
这样这个字段默认就会是 avatar/default.jpg
对应的图片
- 前端处理
前面在 view
中处理的时候是从 request.FILES['file']
中拿到的, 所以前端要发送对应的请求, 这个是要求前端发送的 表单消息格式 是 multipart/from-data
, 也就是 Content-Type
为 multipart/from-data
一般的 html
都可以设定这种类型, 不过在 iOS
中并没有原生的支持, 所以一是自己写一个 HTTP
报文, 或者是使用 AFNetworking
这个框架
- 文件名的问题
如果只是上面这样简单的使用, 文件名是保留为上传时候的文件名, 这样当有重复文件名的图片被接受到时, 原来的就被 覆盖 了, 这就很不友好, 所以文件名一般需要后端这边另外设置一下
ImageField
这个字段在存储时其实也是有自己的文件处理函数, 所以可以把这个文件处理换成我们自己想要的, 在里面更改文件名, 这样就可以达到这个需求; 而这个文件处理类在字段定义的时候就可以赋予了, 不过还有一些操作过程:
在 BASE_DIR
中新建一个文件夹 system
, 进入这个文件夹, 创建一个内容为空的 __init__.py
文件, 创建 storage.py
, 输入以下内容, 也就是你的存储处理类:
1 | # -*- coding: UTF-8 -*- |
(参考了网上的代码) 这个是把文件名改为 年月日时分秒_随机数
在 iOS
这个简单的项目是可以用的了…
最后 ImageField
的定义为:
1 | from system.storage import ImageStorage |
- 用
url
直接访问图片文件
之前说到一般使用 ImageField
的 url
属性, 进一步, 可以让 Django
进行路由, 这样就可以直接通过 url
来访问图片文件了
关键点是设定路由, 在 urls.py
添加, 像下面这样:
1 | # 引入相应库 |
这样路由就设定好了, 可以测试一下看看:
成功!
上传图片测试
用html测试
iOS
关于 multipart/from-data
代码不好写, 就用 html
测试一下:
1 |
|
选择图片
返回消息
查看图片