Django 使用html表单上传图片

图片上传:
一、将图片上传至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),
  1. 配置static根搜索目录;
    在根目录下创建一个static文件夹
    在settings.py文件下:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
  1. 配置图片上传之后,保存的文件目录;默认情况下,Django是将上传的图片保存在本地目录下;MEDIA_ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media/')
  1. 定义一个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'
  1. 在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('第二种方法,图片上传成功')

猜你喜欢

转载自blog.csdn.net/zhangmengran/article/details/83590786