4

My App needs to upload different profile images in different folders inside the static folder. One more thing, I'm not using models, I just want to take the picture I choose in html input file and copy to the specific folder.

Here is my folder tree. Where I want to save the uploaded image is in MYPROJECTFOLDER/static/profile/<TheUserSpecificFolder>/ that's where I don't want to use MEDIA_ROOT, becouse in media root I can't create a specific folder to each user. (I don't know if this is correct, if there is a way to create a specific folder to each user in the /media/ folder without using ImageField or FileField, please tell me).

Here is my folder tree:

MYPROJECTFOLDER
|
|------myproject/
|
|------myapp/
|
|------static
|      |-------profile
|              |------folder_user1
|                     |------ uploadedpicture.jpg #Here is where I want to upload
|                     |------folder_user2

Here is my 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>

Here is my 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')
xyres
  • 20,487
  • 3
  • 56
  • 85
Sergio Mendez
  • 1,311
  • 8
  • 33
  • 56
  • 1
    Why can't you create a folder in the media directory in the same way you are in the static directory? Also, using relative paths is likely to fail at some point (i.e., if/when you deploy your code). –  Dec 30 '17 at 17:32

1 Answers1

8

Since you say that:

I don't want to use MEDIA_ROOT, becouse in media root I can't create a specific folder to each user

Actually, you can. You asked a similar question before and the answer I posted allows you to do that. Simply put, yes, you can create separate folders for users in MEDIA_ROOT. See this answer.


Anyway, if you still want to upload images in a custom folder manually, well, you can do it like this:

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)

Attention!

As per the suggestion made by dahrens in the comment below, here are the reasons why you should keep the static files and media files in separate locations:

  1. Static files are considered to be safe as they come from you, the developer - media files instead come from user land and might need additional attention, so they can not be considered safe without checks.
  2. Media/uploaded files will keep growing as more and more users upload files. With your current approach, you are likely to run out of storage space.
  3. Almost every serious web application hosts the uploaded media files in a separate server, so that storage won't become a problem. That is why it is a good idea to keep uploaded images in MEDIA_ROOT. Because all you have to do is change the value of MEDIA_ROOT and Django will save images there.
xyres
  • 20,487
  • 3
  • 56
  • 85
  • 1
    In general it is worth to mention that the distribution of static and media files is a good idea. The main difference is that static files are considered to be safe as they come from you, the developer - media files instead come from user land and might need additional attention - e.g. they might grow much faster and they can not be considered as safe without checks. You should pick the proper location also with deployment in mind. Small nitpick regarding this straight forward solution: The path should be resolved from django settings instead of assuming the default 'static/'. – dahrens Dec 30 '17 at 19:43
  • @dahrens Thank you for your suggestions, I've update my answer accordingly. However, I left out the part about reading variables from settings, because `STATICFILES_DIRS` can have more than one static directory listed (and then there's `STATIC_ROOT` settings too), so I didn't want to overwhelm OP. But hopefully, they will figure it out soon. – xyres Dec 30 '17 at 20:20
  • @xyres, did you forget to close the file or its intentional? – emanuel sanga Jul 14 '21 at 11:07
  • @emanuelsanga Opening a file using `with open(...)` statement automatically closes the file when the `with` block exits. See: https://stackoverflow.com/q/31334061/1925257. – xyres Jul 14 '21 at 11:16