使用Django在特定文件夹中上传图像而无需使用FileField或ImageField和MEDIAROOT

4
我的应用需要在静态文件夹的不同子文件夹中上传不同的个人资料图片。 还有一件事,我没有使用模型,我只想把我在html输入文件中选择的图片复制到特定的文件夹中。 这是我的文件夹树。我想保存上传的图片在MYPROJECTFOLDER/static/profile/<TheUserSpecificFolder>/中,这就是我不想使用MEDIA_ROOT的原因,因为在媒体根目录下我无法为每个用户创建一个特定的文件夹。(如果有一种方法可以在/media/文件夹中为每个用户创建一个特定的文件夹而不使用ImageFieldFileField,请告诉我)。 这是我的文件夹树:
MYPROJECTFOLDER
|
|------myproject/
|
|------myapp/
|
|------static
|      |-------profile
|              |------folder_user1
|                     |------ uploadedpicture.jpg #Here is where I want to upload
|                     |------folder_user2

这是我的uploadpic.html文件。

<form action="{% url 'upload' %}" enctype="multipart/form-data" method="POST">
  {% csrf_token %}
  <input type="file" name="avatar" accept="image/gif, image/jpeg, image/png">
  <button type="submit">Upload</button>
</form>

这里是我的views.py文件。
from django.shortcuts import render, HttpResponse, redirect
from . import forms
import os

def upload(request):
  img = request.FILES['avatar']
  #This just create the folder where I want to save the image.
  if not os.path.exists('static/profile/' + str(request.session['user_id'])):
    os.mkdir('static/profile/' + str(request.session['user_id']))

  #NOW HERE IS WHERE I WANT TO WRITE THE CODE THAT SAVE THE IMAGE INTO THE FOLDER I JUST CREATED


return redirect('companyedit')

1
为什么不能像在静态目录中那样在媒体目录中创建文件夹?此外,使用相对路径很可能在某些时候会失败(例如,在部署代码时)。 - user8651755
1个回答

8

既然您说:

我不想使用MEDIA_ROOT,因为在媒体根目录中无法为每个用户创建特定的文件夹

实际上,您可以。您之前问过一个类似的问题,我发布的答案允许您这样做。简单来说,是的,您可以在MEDIA_ROOT中为用户创建单独的文件夹。请参见此答案


无论如何,如果您仍然想要手动上传图像到自定义文件夹,那么您可以像这样操作:

def upload(request):
    img = request.FILES['avatar']
    img_extension = os.path.splitext(img.name)[1]

    user_folder = 'static/profile/' + str(request.session['user_id'])
    if not os.path.exists(user_folder):
        os.mkdir(user_folder)

    img_save_path = "%s/%s%s" user_folder, 'avatar', img_extension
    with open(img_save_path, 'wb+') as f:
        for chunk in img.chunks():
            f.write(chunk)

注意!

根据下面评论中dahrens的建议,以下是将静态文件和媒体文件分开存放的原因:

  1. 静态文件被认为是安全的,因为它们来自于开发人员 - 媒体文件来自用户端并可能需要额外的注意,因此没有经过检查就不能被视为安全。
  2. 随着越来越多的用户上传文件,媒体/上传文件将不断增长。按照您当前的方法,您可能会用尽存储空间。
  3. 几乎每个严肃的Web应用程序都将上传的媒体文件托管在单独的服务器上,以便存储不会成为问题。这就是为什么将上传的图像保存在MEDIA_ROOT中是一个好主意。因为你所要做的就是改变MEDIA_ROOT的值,Django就会将图像保存在那里。

1
总的来说,值得一提的是静态文件和媒体文件的分发是个好主意。主要区别在于静态文件被认为是安全的,因为它们来自于你,开发者 - 相反,媒体文件来自用户领域,可能需要额外的注意 - 例如,它们可能会增长得更快,并且如果没有检查,不能被视为安全。您应该选择适当的位置,也要考虑部署。关于这个简单的解决方案的小问题:路径应该从Django设置中解析,而不是假设默认的“static /”。 - dahrens
@dahrens 谢谢您的建议,我已经相应地更新了我的答案。然而,我省略了从设置中读取变量的部分,因为 STATICFILES_DIRS 可以列出多个静态目录(还有 STATIC_ROOT 设置),所以我不想让 OP 感到不知所措。但是希望他们很快就能弄清楚。 - xyres
@xyres,你是忘了关闭文件还是故意的? - emanuel sanga
@emanuelsanga 使用 with open(...) 语句打开文件时,当 with 块退出时会自动关闭文件。参见:https://dev59.com/W10Z5IYBdhLWcg3wiw0v。 - xyres

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接