12 Django上传文件

1 form表单上传文件

enctype="multipart/form-data"在上传文件时,必须写上此参数,可以上传文件也可以上传普通健值

如果不填写,则默认是enctype="application/x-www-form-urlencoded"

<h3>form表单上传文件</h3>
<form action="/upload_file/" method="post" enctype="multipart/form-data">
    <p><input type="file" name="stu_jpg"></p>
    <input type="submit">
</form>
def index(request):
    return render(request,"index.html")

def form_rec(request):
    # 1.获取数据
    stu_jpg = request.FILES.get('stu_jpg')
    print("FILES:", stu_jpg)

    # 2.保存文件
    import os
    path = os.path.join('media', stu_jpg.name)
    with open(path, 'wb') as f:
        for line in stu_jpg:
            f.write(line)

    return HttpResponse('上传成功')

2 Ajax(基于FormData)

FormData是什么呢?

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.

所有主流浏览器的较新版本都已经支持这个对象了,比如Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。

<h3>Ajax上传文件</h3>

<p><input type="text" name="username" id="username" placeholder="username"></p>
<p><input type="file" name="upload_file_ajax" id="upload_file_ajax">
</p>

<button id="upload_button">提交</button>
<span class="err"></span>
{#注意button标签不要用在form表单中使用#}

<script>
    $("#upload_button").click(function(){

        var username=$("#username").val();
        var upload_file=$("#upload_file_ajax")[0].files[0];

        var formData=new FormData();
        formData.append("username",username);
        formData.append("upload_file_ajax",upload_file);

        $.ajax({
            url:"/upload_file/",
            type:"POST",
            data:formData,
            contentType:false,
            processData:false,

            success: function (res) {
                console.log(res)
                if (res.state){
                    $('.err').html(res.msg)
                }else {
                    $('.err').html(res.msg)
                }
            }
        });

    })
</script>
def index(request):
  
    return render(request,"index.html")
  
  
def upload_file(request):
    # 1.获取数据
    stu_jpg = request.FILES.get('username')
    print("FILES:", stu_jpg)

    # 2.保存文件
    import os
    path = os.path.join('media', stu_jpg.name)
    with open(path, 'wb') as f:
        for line in stu_jpg:
            f.write(line)

    res = {'state': True, 'msg': "ajax上传成功"}

    return JsonResponse(res)

3 ImageField 和 FileField

ImageField 和 FileField 可以分别对图片和文件进行上传到指定的文件夹中。

1.在下面的 models.py 中 :

picture = models.ImageField(upload_to='avatars/', default="avatars/default.png",blank=True, null=True) 
# 注:定义 ImageField 字段时必须制定参数 upload_to这个字段要写相对路径,

这个参数会加在 settings.py 中的 MEDIA_ROOT后面, 形成一个路径, 这个路径就是上 传图片的存放位置,默认在Django项目根路径下,也就是MEDIA_ROOT默认是Django根目录

所以要先设置好 mysite/settings.py中的 settings.py 中的 MEDIA_ROOT

class Userinfo(models.Model):
    name = models.CharField(max_length=32)
    avatar_img = models.FileField(upload_to="avatars/") 
    # 上传的文件,存放在Django下的 media/avatars 文件夹下
username = request.POST.get("username")
#获取文件对象
file = request.FILES.get("file")   
#插入数据,将图片对象直接赋值给字段
user = Userinfo.objects.create(name=username,avatar_img=file)

Django会在项目的根目录创建avatars文件夹,将上传文件下载到该文件夹中,avatar字段保存的是文件的相对路径。


2.在 mysite/settings.py中 :

MEDIA_ROOT = os.path.join(BASE_DIR,"media")
MEDIA_URL='/media/'

MEDIA_ROOT:存放 media 的路径, 这个值加上 upload_to的值就是真实存放上传图片文件位置

MEDIA_URL:给这个属性设值之后,静态文件的链接前面会加上这个值,如果设置这个值,则UserInfo.avatar.url自动替换成:/media/avatars/default.png,可以在模板中直接调用:


3.url.py:

from django.views.static import serve
# 添加media 配置
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),

浏览器可以直接访问http://127.0.0.1:8000/media/yuan/avatars/%E7%86%8A%E7%8C%AB.webp,即我们的用户上传文件。

最后再给大家补充一个用户文件夹路径:动态路径字符串

def user_directory_path(instance, filename):
    # instance当前的数据,filename 文件夹名称
    return os.path.join(instance.name,"avatars", filename)

class Userinfo(models.Model):
    name = models.CharField(max_length=32)
    avatar_img = models.FileField(upload_to=user_directory_path)  


4.FileField 和 ImageFiled 相同。


5.示例:

settings.py

MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01.views import index, create_user
from django.views.static import serve
from Uploads import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', index),
    path('create_user/', create_user),
    re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]

views.py

def index(request):
    return render(request, 'index.html')

def create_user(request):
    res = {'state': True, 'msg': "ajax上传成功"}
    username = request.POST.get("user")
    file = request.FILES.get("file")

    user = UserInfo.objects.create(name=username, avatar_img=file)
    res['username'] = user.name
    # user.avatar_img
    res['avatar_url'] = user.avatar_img.url
    return JsonResponse(res)

models.py

from django.db import models
import os

def user_directory_path(instance, filename):
    # instance当前的数据avatar_img,filename 文件夹名称
    return os.path.join(instance.name, "avatars", filename)


class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    avatar_img = models.ImageField(upload_to=user_directory_path)
    # upload_to="/uploads/" :相对路径

index.html

<h3>ImageField/FileField上传</h3>
<div>
    <input type="text" class="user">
    <input type="file" class="stu_avatar">
    <button class="ajax_btn2">ajax提交</button>
    <span class="err2"></span>
    <p>用户名:<span class="user"></span></p>
    <p>用户头像路径:<span class="avatar_url"></span></p>
    <p class="avatar_img"></p>
</div>

<script>
    $(".ajax_btn2").click(function () {
        var formData = new FormData();
        formData.append("user", $('.user').val());
        formData.append("file", $('.stu_avatar')[0].files[0]);
        formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
        $.ajax({
            url: "/create_user/",
            type: "post",
            data: formData,
            contentType: false,
            processData: false,
            success: function (res) {
                console.log(res)
                if (res.state){
                    $('.err2').html(res.msg)
                    $('.user').html(res.username)
                    $('.avatar_url').html(res.avatar_url)

                    $('.avatar_img').append(`<img src="${res.avatar_url}">`)
                }else {
                    $('.err2').html(res.msg)
                }
            }
        })
    })
</script>

4 导入表格批量创建数据

# Create your tests here.
def multi_create(request):
    # 将接受到的excel文件转到mysql
    # (1)下载文件到服务器

    emp_excel = request.FILES.get("emp_excel")
    print(emp_excel) # 期末题目(陕西联通).xlsx
    print(emp_excel.name) # "期末题目(陕西联通).xlsx"
    # 下载文件
    with open("files/"+emp_excel.name,"wb") as f:

        for line in emp_excel:
            f.write(line)


    # 读取excel,批量导入到mysql中

    import os
    from openpyxl import load_workbook
    file_path = os.path.join("files",emp_excel.name)

    # 加载某一个excel文件
    wb = load_workbook(file_path)
    # 获取sheet对象
    print("wb.sheetnames",wb.sheetnames)# 获取所有工作簿的名字
    worksheet = wb.worksheets[0] # 获取execl表中的第一个工作薄对象
		stu_list = []
    for line in worksheet.iter_rows(min_row=3): # 用一行数据拿一行数据;从第三行拿数据
        # print("line", line)
        # for cell in line:  # 取每一行的单元格
        #     print(cell.value)  # 拿去单元格的值
        if line[0].value == None:
            break
        sd = StudentDetail.objects.create(tel=line[4].value, addr=line[5].value)  # 创建学生详情信息
        class_id = Clas.objects.get(name=line[-1].value).id # 获取班级id

        if line[2].value == "男":
            sex = 1
        elif line[2].value == "女":
            sex = 0
        else:
            sex = 2

        stu = Student(
            name=line[0].value,
            age=line[1].value,
            sex=sex,
            birthday=line[3].value,
            clas_id=class_id,
            stu_detail=sd,
        )

        stu_list.append(stu)

    Student.objects.bulk_create(stu_list)  # 批量创建学生


    return redirect("/index/")
posted @ 2022-08-11 11:14  角角边  Views(216)  Comments(0)    收藏  举报