准备工作

在setings.py中加上注册地址

  1. 静态文件地址STATICFILES_DIRS,可以通过static路径访问静态资源。
    1
    2
    3
    STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
    ]
  2. 图片上传存储地址MEDIA_ROOT
    1
    MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')

文件上传

基础方法

  1. 上传界面,对文件进行分包加密enctype=”multipart/form-data”

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    </head>
    <body>
    <form action="{% url 'app:upload_file' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <span>文件:</span>
    <input type="file" name="icon">
    <br>
    <input type="submit" value="上传">
    </form>
    </body>
    </html>
  2. 后台接收,以固定的地址和固定的名称进行存储,通过chunks方法一块块接收,并写入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def upload_file(request):
    if request.method == "GET":
    return render(request, 'upload.html')
    elif request.method == "POST":
    icon = request.FILES.get("icon")
    print(icon, type(icon))
    with open("static/img/icon.png", 'wb') as save_file:
    for part in icon.chunks():
    save_file.write(part)
    save_file.flush()
    return HttpResponse("文件上传成功")

进阶方法

  1. 在models.py 创建对应类
    在过程中需要安装pillow依赖pip install pillow
    Linux中一个文件夹中文件存储上限65535,会打不开文件夹。
    所以在upload_to中以年月日进行存储,这样就不会一直存储在一个文件夹中。
    1
    2
    3
    4
    5
    class UserModel(models.Model):
    u_name = models.CharField(max_length=16)
    # upload_to 相对路径 相对于的是MEDIA_ROOT 媒体根目录
    # u_icon = models.ImageField(upload_to="icons") 指定icons目录
    u_icon = models.ImageField(upload_to="%Y/%m/%d/icons") # 根据时间进行分开存储
  2. 上传界面与上面无差别
  3. 后台接收
    直接调用UserModel,然后赋值存储。同名的文件会自动加尾缀重命名。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def image_field(request):
    if request.method == "GET":
    return render(request, 'image_field.html')
    elif request.method == "POST":
    username = request.POST.get("username")
    icon = request.FILES.get("icon")
    user = UserModel()

    user.u_name = username
    user.u_icon = icon
    user.save()
    return HttpResponse('上传成功%d' % user.id)

遇到的问题

1. context must be a dict rather than set.

在获取个人信息时,往context中传入data时,简写并不适用。如下,定义了用户名和用户头像。

1
2
3
username = request.GET.get("username")
user = UserModel.objects.get(u_name=username)
icon_url = "/static/upload/" + user.u_icon.url
  1. 错误写法:
    1
    2
    3
    4
    5
    data = {
    username,
    icon_url
    }
    return render(request, "mine.html", context=data)
  2. 正确写法:
    1
    2
    3
    4
    5
    data = {
    'username': username,
    'icon_url': icon_url
    }
    return render(request, "mine.html", context=data)

2. request.Files.get获取不到文件

在上面获取图片内容时request.FILES.get(“icon”)一直为NoneType,获取不到对应的图片信息。

  1. 表单中的name是否和get中参数对应

    1
    <input type="file" name="icon">
  2. 表单没有填写 enctype=”multipart/form-data”

    1
    2
    3
    4
    5
    6
    7
    <form action="{% url 'app:upload_file' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <span>文件:</span>
    <input type="file" name="icon">
    <br>
    <input type="submit" value="上传">
    </form>

3. expected str, bytes or os.PathLike object, not list
由于自己对django的基础掌握不是很牢固,忽略了MEDIA_ROOT的类型是string,而不是list。

  1. 错误写法:
    1
    2
    3
    MEDIA_ROOT = [
    os.path.join(BASE_DIR, 'static/upload'),
    ]
  2. 正确写法:
    1
    MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')