如何使用S3boto3存储在Django中上载图像,其中路径是从Django中的视图动态设置的

2024-09-30 01:37:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在django中将session_键作为存储桶中的目录,将图像保存到S3存储桶中

我创建了一个测试页面,将图像上传到bucket中的一个设置位置,但不知道如何使用session_键动态设置上传位置

我已经查看了django-storages的文档,如果不是因为我正在使用ModelForm,我可以找到一种方法来实现这一点

以下是我的代码(我省略了带有bucket名称和凭据的settings.py):

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>

screenshot of rendered template page showing upload of image

当我运行代码并上传一个图像时,例如car.jpg,它会成功上传,但S3 bucket内的路径是

<bucket-name>/dev/car.jpg

我想要

<bucket-name>/dev/<session-key>/car.jpg

需要的包是boto3django-storages,以防任何想要帮助回答问题的人需要知道


Tags: djangofrompyimportformifs3bucket
1条回答
网友
1楼 · 发布于 2024-09-30 01:37:28

我找到了一种方法,可以使用会话密钥将图像/文件上传到s3的目录中。它也适用于上传文件,而不仅仅是s3

首先,我向模型添加了一个属性来存储会话密钥

class TestS3Upload(models.Model):
    session_key = models.CharField(max_length=50, null=False, blank=False)
    ...

然后,我在modelform中包含了一个隐藏字段,在视图中预先填充了session_key

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})

然后,我在我的models.py中创建了一个函数,该函数使用模型中的session_键返回路径,并将模型的file field upload_to属性设置为该函数

...
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)

现在保存表单时,它会使用session_键将文件上载到目录中

最后的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
        }
    )

view test_s3_upload.html的模板保持不变

Upload success message with full url path to uploaded file

相关问题 更多 >

    热门问题