图片上传:
一、将图片上传至static文件夹下;
二、 将图片上传至自定义文件夹下;
第一种:上传至static文件夹下;
步骤为下:
通过html表单实现图片的上传;
a>Model中的图片字段可以写成models.ImageField()也可以写成models.CharField(),只不过,ImageField()及其upload_to是失效的,完全相当于是一个CharField();
b>图片上传的路径,需要自己指定,并且文件夹需要手动创建;
url = settings.MEDIA_ROOT + ‘images/’ + pic.name
with open(url, ‘wb’) as f:
# pic.chunks()循环读取图片内容,每次只从本地磁盘读取一部分图片内容,加载到内存中,并将这一部分内容写入到目录下,写完以后,内存清空;下一次再从本地磁盘读取一部分数据放入内存。就是为了节省内存空间。
for data in pic.chunks():
f.write(data)
首先,在urls.py中绑定路由
path('upload/', uploadimg),
- 配置static根搜索目录;
在根目录下创建一个static文件夹
在settings.py文件下:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
- 配置图片上传之后,保存的文件目录;默认情况下,Django是将上传的图片保存在本地目录下;MEDIA_ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media/')
- 定义一个Model类,在Model中声明一个用于保存图片地址的字段,放在数据库的表中;
在models.py文件中,创建一个Model类
class PictureModel(models.Model):
# 该字段用于保存图片上传之后的地址;
# upload_to: 指明图片在MEDIA_ROOT目录下的具体存放目录。如果不指定这个参数,默认所有的图片都保存在MEDIA_ROOT目录下。/static/media/imguploadapp/1.jpg
# upload_to如果指定了目录,目录需要自己手动创建。
pic_url = models.CharField(max_length=50)
class Meta:
db_table = 'picture'
- 在html文件中添加上传图片的表单;
在views.py中实现函数
from django.shortcuts import render
from .models import PictureModel
from django.conf import settings
from django.http import HttpResponse
"""
图片上传:
1. 将图片上传至static文件夹下;
2. 将图片上传至自定义文件夹下;
"""
def uploadimg(request):
if request.method == 'GET':
# img = PictureModel.objects.get(id=18)
# return render(request, 'index.html', {'img': img})
return render(request, 'index.html')
else:
# 需要从表单input中,获取上传的文件对象(图片)
pic = request.FILES.get('picture')
# 1. 创建Model对象,保存图片路径到数据库
model = PictureModel()
model.pic_url = pic.name
model.save()
# 2. 开始处理图片,将图片写入到指定目录。(/static/media/imguploadapp/)
# 拼接图片路径
url = settings.MEDIA_ROOT + 'images/' + pic.name
with open(url, 'wb') as f:
# pic.chunks()循环读取图片内容,每次只从本地磁盘读取一部分图片内容,加载到内存中,并将这一部分内容写入到目录下,写完以后,内存清空;下一次再从本地磁盘读取一部分数据放入内存。就是为了节省内存空间。
for data in pic.chunks():
f.write(data)
return HttpResponse('图片上传成功')
创建一个index.html,
<body>
<form action="/upload/" method="post" enctype="multipart/form-data">
{# application/x-www-form-urlencoded: username='123'&password='456' 适合文本 #}
{# multipart/form-data: 以指定的分隔符对上传数据进行分割 适合二进制文件 #}
{# 上传图片相当于上传数据,一定要使用POST请求,并且要指定一个属性enctype #}
{% csrf_token %}
<input type="file" name="picture">
<button type="submit">上传</button>
</form>
<img src="/static/media/{{ img.pic_url }}" alt="">
</body>
这样,就可以在HTML表单中上传图片了。
但是,
上面的函数中,使用for循环的写法适合大文件的上传和读取,达到节省内存的目的
如果是小文件可以采用另外一种方式,并且可以配合着ImageField(upload_to)使用,并且会自动创建upload_to中指定的目录。
将models.py文件中,改成ImageField的格式
from django.db import models
class PictureModel(models.Model):
# 该字段用于保存图片上传之后的地址;
# upload_to: 指明图片在MEDIA_ROOT目录下的具体存放目录。如果不指定这个参数,默认所有的图片都保存在MEDIA_ROOT目录下。/static/media/imguploadapp/1.jpg
# upload_to如果指定了目录,目录需要自己手动创建。
pic_url = models.ImageField(upload_to='small_pic')
class Meta:
db_table = 'picture'
在views.py中的函数,进行更改
def uploadimg(request):
if request.method == 'GET':
# img = PictureModel.objects.get(id=18)
# return render(request, 'index.html', {'img': img})
return render(request, 'index.html')
if request.method == 'POST':
img = PictureModel(pic_url=request.FILES['picture'])
img.save()
return HttpResponse('第二种方法,图片上传成功')