django文件上传到数据库 调用并显示 文件的预览与下载

django 原生文件上传
#html页面
<form action="/upload/" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <p>姓名:<input type="text" name="sname"></p>
    <p>图片:<input type="file" name="photo"></p>
    <p><input type="submit" value="提交"></p>
</form>

# 注意注意啦:文件上传必须写method="post" enctype="multipart/form-data

#views.py文件代码:
from django.http import HttpResponse
from django.shortcuts import render
import os
from demo6.settings import BASE_DIR

def upload_index(request):
    if request.method == "GET":
        return render(request,"upload.html")
    elif request.method == "POST":
        # 获取请求参数
        sname = request.POST.get("sname")
        photo = request.FILES.get("photo")
        # print(type(photo))的输出结果为上传文件对象,如下
        # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
        # print(photo)的输出结果如下
        # 1567516976(1).jpg

        # 判断文件目录是否存在
        # settings.py文件中 
        # BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
		# 指的是当前文件 的绝对路径 的目录 的目录
        m_path = os.path.join(BASE_DIR, "images")  # images指的是文件夹名
        if not os.path.exists(m_path):
        	# 如果项目目录下没有images目录,则会新建一个
            os.mkdir(m_path)

        
        with open(os.path.join(m_path,photo.name), "wb") as f:
            # 一次性将文件读取到内存
            # f.write(photo.read())

            #分块读取文件到内存
            for c in photo.chunks():
                f.write(c)

        return HttpResponse("上传成功")
  • photo.read():从文件中读取整个上传的数据,这个方法只适合小文件;
  • photo.chunks():按块返回文件,通过在for循环中进行迭代,可以将大文件按块写入到服务器中;
  • photo.multiple_chunks():这个方法根据myFile的大小,返回True或者False,当myFile文件大于2.5M(默认为2.5M,可以调整)时,该方法返回True,否则返回False,因此可以根据该方法来选择选用read方法读取还是采用chunks方法
  • photo.name:这是一个属性,不是方法,该属性得到上传的文件名,包括后缀,如123.exe;
  • photo.size:这也是一个属性,该属性得到上传文件的大小。
Django文件上传到数据库 并调用显示在页面中
并实现文件的预览与下载

环境:Python 3.6.0 Django 2.2.4

需求
  1. 完成学生信息注册操作 访问路径 GET /student/upload/ POST /student/upload/
  2. 将表单数据保存到数据库 访问路径 GET /student/upload/ POST /student/upload/
  3. 将上传文件存放至项目下media文件夹下
  4. 将用户提交的数据显示在页面中 访问路径 GET /student/showall/
创建模型类
from django.db import models

class Student(models.Model):
    sname = models.CharField(max_length=30)
    age = models.PositiveIntegerField()
    photo = models.ImageField(upload_to='imgs/')
    # 上面要写相对路径前面不能加/
    # 上传文件(ImageField,FileField)
    # 如果创建的表中有ImageField数据类型,要先pip install Pillow
    # 图片保存到项目下的某个文件夹下
    # upload_to='imgs/'默认保存到项目根目录下的imgs文件夹下面
    # 本质文件上传后存储的位置=setting.py文件MEDIA_ROOT + UPLOAD_to

settings.py文件中文件上传相关设置
# 引包
# global_settings

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# BASE_DIR指的是项目根目录
# 我们需要告诉Django,媒体文件的位置在哪里。
# 这样就和数据库存储的路径相对应了,具体就是MEDIA_ROOT指定目录,upload_to就是在这个目录下进行操作。
映射数据库表
#在终端中敲命令
python manage.py makemigrations stu
python manage.py migrate


配置URL
  • test13/urls.py
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path("student/", include("stuapp3.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

# serve是Djando提供的视图函数,读取上传文件
# if DEBUG:
# urlpatterns += re_path('media/(?P<path>.*)/', serve, {"document_root": MEDIA_ROOT}),
# 上面的这种配置只适用于Django 1.X版本
# path:imgs/1.jpg
# document_root:media文件夹的绝对路径
# url = d/phthonproject/.../media/imgs/1.jpg

  • stu/urls.py
from django.urls import path
from stuapp3 import views

urlpatterns = [
    path("upload/", views.upload1_view),
    path("showall/", views.showall_view)
]
创建视图
  • stu/views.py
from django.http import HttpResponse, Http404
from django.shortcuts import render
from stuapp3.models import Student

def upload1_view(request):
    # 表单提交的请求方式只支持get或者post
    # 针对其他的请求方式需要使用AJAX
    if request.method == "GET":
        return render(request, "upload.html")
    else:
        # 获取请求参数
        sname = request.POST.get("sname", "")
        age = request.POST.get("age", "")
        photo = request.FILES.get("photo", "")

        # 校验上传图片的格式(png/jpg)
        # 获取文件扩展名
        extendname = photo.name[photo.name.rindex(".") + 1:]
        # 判断上传文件是否符合格式要求
        allowedes = ["png", "jpg"]
        if extendname not in allowedes:
            return Http404()

        # 将数据保存到数据库
        stuObj = Student.objects.create(sname=sname,age=age,photo=photo)

        # 判断是否注册成功
        if stuObj:
            return HttpResponse("注册成功")
        return HttpResponse("注册失败")


def showall_view(request):
    # 查询所有学生信息
    stus = Student.objects.all()
    return render(request, 'showall.html', {'stus': stus})

创建模板
  • templates/upload.html
<body>
    <form action="/student/upload/" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p>姓名:<input type="text" name="sname"></p>
        <p>年龄:<input type="text" name="age"></p>
        <p>头像:<input type="file" name="photo"></p>
        <p>&nbsp;&nbsp;<input type="submit" value="提交"></p>
    </form>
</body>

  • templates/showall.html
<body>
    <table border="1" width="500px" cellspacing="0">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>头像</th>
            <th>操作</th>
        </tr>
        {% for stu in stus %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ stu.sname }}</td>
                <td>{{ stu.age }}</td>
                <td><img style="width: 100px" src="{{ MEDIA_URL }}{{ stu.photo }}"/></td>
                <td>操作</td>
            </tr>
        {% endfor %}
    </table>
</body>

这里{{ MEDIA_URL }}是必须要的,因为数据库取出来的地址是/logo/img001.png这种,路径不完整,我们存储的路径上/media/logo/img001.png

但到这里还是不能正常显示图片,会显示404,是因为图片的url也是需要通过django进行指派,我们还需要在urls.py进行设定。

为了html模板能正确找到MEDIA_URL,TEMPLATES中导入相关的包。如下所示
头像读取相关settings.py文件中的设置

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.media'#配置这句话
            ],
        },
    },
]

文件下载 访问路径GET /student/download/

配置子路由URL
from django.urls import path, re_path
from stuapp3 import views

urlpatterns = [
    path("upload/", views.upload1_view),
    path("showall/", views.showall_view),
    re_path("download/(.*)$", views.download_view)
]
创建视图
def download_view(request, photoname):
    # 接受请求参数
    flag = request.GET.get("flag", "")

    # 获取上传的文件名 imgs/1.jpg
    filename = photoname[photoname.rindex("/")+1:]

    # 获取文件所在的存储位置
    url = os.path.join(MEDIA_ROOT, photoname)

    # 预览模式
    with open(url, "rb") as f:
        content = f.read()
    response = HttpResponse(content, content_type="image/jpeg")
    if flag == "2":
        # 附件下载模式
        response["Content-Disposition"] = "attachment;filename="+filename
    return response

文件名中文情况
from django.utils.encoding import escape_uri_path

response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name))


<body>
    <table border="1" width="500px" cellspacing="0">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>头像</th>
            <th>操作</th>
        </tr>
        {% for stu in stus %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ stu.sname }}</td>
                <td>{{ stu.age }}</td>
                <td><img style="width: 100px" src="{{ MEDIA_URL }}{{ stu.photo }}"/></td>
                <td>
                    <a href="/student/download/{{ stu.photo }}?flag=1">预览查看</a>
                    <a href="/student/download/{{ stu.photo }}?flag=2">附件下载</a>
                </td>
            </tr>
        {% endfor %}
    </table>
</body>

  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值