I'm wanting to save images to an S3 bucket using the session_key as the directory inside the bucket, in django.
I have created a test page that uploads an image to a set location in the bucket but don't know how to use the session_key to set the upload location dynamically.
I've looked at the docs for django-storages
and I can see a way to do this if it wasn't for the fact that I am using a ModelForm
.
Here is the code I have (I have omitted my settings.py with the bucket name and credentials):
storage_backends.py
from storages.backends.s3boto3 import S3Boto3Storage
class TestS3MediaStorage(S3Boto3Storage):
location = 'dev/'
default_acl = 'public-read'
file_overwrite = False
models.py
from .storage_backends import TestS3MediaStorage
class TestS3Upload(models.Model):
uploaded_at = models.DateTimeField(auto_now_add=True)
file = models.FileField(storage=TestS3MediaStorage())
forms.py
from .models import TestS3Upload
class TestS3UploadForm(forms.ModelForm):
class Meta:
model = TestS3Upload
fields = ['file']
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import TestS3UploadForm
def test_s3_upload(request):
# create session if it doesn't already exist
if not request.session.session_key:
request.session.create()
# not quite sure how to use this to set upload destination
session_key = request.session.session_key
if request.method == 'POST':
form = TestS3UploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponse("upload successful!")
else:
form = TestS3UploadForm()
return render(
request,
'uploader/test_s3_upload.html',
{
'form': form
}
)
test_s3_upload.html
<h1>Test S3 file upload</h1>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload photo to S3 Bucket</button>
</form>
When I run my code and upload an image, for example car.jpg
, it uploads successfully but the path inside the S3 bucket is
<bucket-name>/dev/car.jpg
and i want
<bucket-name>/dev/<session-key>/car.jpg
The packages needed are boto3
and django-storages
in case anyone who wants to help answer needs to know.
I have figured out a way to upload an image/file to s3 to a directory using the session key. It also works for uploading a file in general, not just s3.
First I added an attribute to the model to store the session key.
class TestS3Upload(models.Model):
session_key = models.CharField(max_length=50, null=False, blank=False)
...
Then I included a hidden field on the modelform that I pre-populated with the session_key
value in the view.
forms.py
class TestS3UploadForm(forms.ModelForm):
class Meta:
model = TestS3Upload
fields = ['file', 'session_key']
widgets = {'session_key': forms.HiddenInput()}
views.py
def test_s3_upload(request):
# create session if it doesn't already exist
if not request.session.session_key:
request.session.create()
session_key = request.session.session_key
...
form = TestS3UploadForm(initial={'session_key': session_key})
Then I created a function in my models.py
that returns a path using the session_key from the model and set the model's file field upload_to
attribute to this function
...
import os
def upload_to_session_key_dir(instance, filename):
return os.path.join(instance.session_key, filename)
class TestS3Upload(models.Model):
session_key = models.CharField(max_length=50, null=False, blank=False)
uploaded_at = models.DateTimeField(auto_now_add=True)
file = models.FileField(upload_to=upload_to_session_key_dir)
When saving the form now it uploads the file inside a directory with the session_key.
final views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import TestS3UploadForm
from .models import TestS3Upload
def test_s3_upload(request):
# create session if it doesn't already exist
if not request.session.session_key:
request.session.create()
session_key = request.session.session_key
if request.method == 'POST':
form = TestS3UploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
filename = "{}/{}".format(session_key, form.cleaned_data['file'].name)
s3_upload_path = TestS3Upload.objects.get(file=filename).file.url
return HttpResponse("Image successfully uploaded to bucket at location: {}".format(s3_upload_path))
else:
form = TestS3UploadForm(initial={'session_key': session_key})
return render(
request,
'upload/test_s3_upload.html',
{
'form': form
}
)
The template for the view test_s3_upload.html remained the same.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.