Episode 11 of 13

Uploading Files with HTMX & S3

Learn about Uploading Files with HTMX & S3

Why Use S3 for File Storage?

Storing uploaded files on the local filesystem works for development, but in production you need a cloud storage solution. Amazon S3 (Simple Storage Service) is the most widely used object storage service. It provides virtually unlimited storage, built-in redundancy, and global content delivery capabilities.

Setting Up an S3 Bucket

Log into the AWS Management Console and navigate to S3. Create a new bucket with a unique name like "django-htmx-contacts-media". Configure the bucket to allow public read access for the uploaded images, since they will be displayed on the website. Set up a CORS policy that allows requests from your domain.

Installing django-storages and boto3

Install the packages needed to connect Django to S3:

pip install django-storages boto3

Add "storages" to your INSTALLED_APPS in settings.py.

Configuring Django Settings

In settings.py, add the AWS configuration variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_STORAGE_BUCKET_NAME, and AWS_S3_REGION_NAME. Set the DEFAULT_FILE_STORAGE to "storages.backends.s3boto3.S3Boto3Storage" so Django automatically uploads media files to S3 instead of the local filesystem.

HTMX File Upload Configuration

Ensure your form element has the hx-encoding="multipart/form-data" attribute. HTMX needs this to correctly encode file data in the AJAX request. The Django view receives the file in request.FILES just like a normal form submission. When form.save() is called, django-storages automatically handles the upload to S3.

Displaying Uploaded Images

In your contact display templates, use the contact.photo.url attribute to get the full S3 URL of the uploaded image. Display it in an img tag. Add appropriate sizing and a rounded class for profile photos. Handle the case where no photo has been uploaded by showing a default placeholder avatar.