django -- ImageField 上传图片修改头像
django -- ImageField 上传图片修改头像
折腾了差不多一个星期的空闲时间,刚上手不久的 Django 为了上传个头像被弄得没了脾气
定义模型 model.py
headImg = models.ImageField(upload_to = 'img', default="img/4.jpg")
ImageField 是 Django 的内置数据类型,可以较方便的时间图片处理
upload_to 表示要上传到的目录,会在 media 目录下自动创建,不用加斜杠,不过在实践中发现好像不起作用
default 表示默认图片路径,总不能一开始显示 alt 的内容吧
修改配置 setting.py
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname('__file__')))
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media/img')
MEDIA_URL = "/head/"
PROJECT_ROOT 表示项目的根目录
经过拼接后的 MEDIA_ROOT 就是我们头像的绝对路径了,media 创建在根目录下,那个 img 目录是我自己创建的,可能是姿势不对,反正上面说到的 upload_to 没有自动创建好
还有一个就是 MEDIA_URL,这个是我们访问图片的链接,举例来说如果我们的 MEDIA_ROOT 是 D:/project_name/media/img/ 的话,当我们访问 127.0.0.1:8000/head/img/4.jpg 时,实际上就是访问 D:/project_name/media/img/4.jpg 了,自己实践理解的还是跟网上的博客有些出入
于是我们就可以在 html 上这样表示图片了
<img src="{{ MEDIA_URL }}img/4.jpg">
详细了解这方面的话,可以参考这里,不过以我的理解是有出入的,可能是我错了吧,好像就是 upload_to 这里出现的问题
Django下MEDIA_ROOT, MEDIA_URL, STATIC_ROOT, STATIC_URL解惑
值得注意的是,虽然 MEDIA_ROOT 也是存储静态文件的,但是应该和 STATIC 区别开来,不要以为配置了 STATIC 的就可以不同 MEDIA 了,个人理解,应该是 ImageField 中有 media 相关的连接吧
前端
来到前端这边,表单之类的创建就忽略了,可以直接使用 Django 的表单,也可以使用 html 表达,不过在 <form>
标签中,应该添加这个属性
enctype="multipart/form-data"
如果不加的话,上传的图片就会变成空的了,原因不知
后台 views.py
自然,该后台处理了,也就是 views.py
首先是获取前台的图片信息,第二个 input_img 表示上传标签的属性名
第一个 input_img 是一个对象,有 name , url 等属性
if request.method == 'POST':
input_img = request.FILES['input_img']
然后就是数据库更新了
models.UserProfile.objects.filter(username=username).update(headImg = input_img)
这里的 username 是我登录时保存的 session 值,具体是怎样获得的还是得看个人
另外,后台的图片怎样显示在前端,这个就用上了 ImageField 对象的一些属性了
# views.py 中,传递到前端
user_info = models.UserProfile.objects.get(username=username)
# 传递到前端
return render(request, 'complete.html',{'user_info':user_info})
# 前端页面,headImg 是 model.py 中定义的
<img alt="aaa" src="{{ user_info.headImg.url }}">
本来到这步已经算是大功告成了,因为看到数据库的数据被更新了,而且很多博客资料都说 ImageField 是会处理很多的琐事的,包括把图片放到该放的文件夹
但是,然而并没有,相应的 img 目录下并没有出现新的头像文件,所以显示的时候只能是 Not Found 了,还是,我姿势又是错误的
查看了相关的文档,只能直接用 python 代码实现保存图片了
from PIL import Image
if input_img:
img=Image.open(input_img)
img.save('E:/package_1.0/media/img/'+input_img.name)
这里使用了 PIL 库,了解一下基本的就可以使用了
有一个问题,就是 save 的路径,使用相对路径一直出错,只能改为绝对路径了
然后就算是大功告成了,不过,还是前路漫漫
总结
折腾了这么久,写起这些来却是简短的要命,还是得开窍多一点才行
以后如果遇到照着例子敲的时候错误百出的情况,还是好好去弄懂原理吧,这样走起路或许会安慰许多,当然,得时间允许的情况下