Images are uploaded into S3 but URL within django application is not displaying correctly
Problem
I am able to upload images into S3, however the structure of the URL within my django app is not structured properly.
The URL appears like this: http://localhost:8000/plants/https://'%s.s3.amazonaws.com'%AWS_STORAGE_BUCKET_NAME/media/plant_images/image.jpeg
However, I want it to appear as https://opensprouts-dev-media.s3.amazonaws.com/media/plant_images/images.jpeg
Context
I have a model that allows me to upload multiple images. I think I need to rewrite the way I call for the image within my template, or within my model. After reading through Django documentation and other stackoverflow questions, I'm not sure how to resolve this issue.
settings.py/base.py
# MEDIA
# ------------------------------------------------------------------------------
USE_S3 = os.getenv('USE_S3') == 'TRUE'
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
AWS_QUERYSTRING_AUTH = config('AWS_QUERYSTRING_AUTH')
AWS_S3_CUSTOM_DOMAIN = config('AWS_S3_CUSTOM_DOMAIN')
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = config('AWS_LOCATION')
PUBLIC_MEDIA_LOCATION = 'media'
AWS_QUERYSTRING_AUTH = False
MEDIA_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATIN)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
The section of my template that is calling for the URL {{ image.images.url }}
{% for image in plant.plant_images.all %}
{% if forloop.first %}
<div class="carousel-item active">
{% else %}
<div class="carousel-item">
{% endif %}
<img src="{{ image.images.url }}" alt="{{ plant.name }}">
</div>
{% endfor %}
</div>
models.py
import datetime
from django.conf import settings
from django.db import models
from django.utils import timezone
from django.template.defaultfilters import slugify
from django.urls import reverse
from django_quill.fields import QuillField
# Create your models here.
class Plant(models.Model):
name = models.CharField(max_length=120)
slug = models.SlugField(null=False, unique=True)
description = models.TextField()
def __str__(self):
return self.name
def publish(self):
self.published_date = timezone.now()
self.save()
def get_absolute_url(self):
return reverse("plant_detail", kwargs={"slug": self.slug})
class PlantImage(models.Model):
plant = models.ForeignKey(Plant, default=None, on_delete=models.CASCADE, related_name="plant_images")
images = models.ImageField(upload_to = 'plant_images/')
def __str__(self):
return self.plant.name
views.py
from .models import Plant, PlantImage
def plant_index(request):
plant_objects = Plant.objects.all()
context = {'plant_objects': plant_objects}
return render(request, 'plants/plant_index.html', context)
class PlantDetailView(DetailView):
model = Plant
template_name = 'plants/plant_detail.html'
slug = 'slug'
def get_context_data(self, **kwargs):
context = super(PlantDetailView, self).get_context_data(**kwargs)
context['plant_images'] = PlantImage.objects.all()
return context
plant_detail = PlantDetailView.as_view()
I can see the images are successfully being stored in s3 after I upload them via my Django backend UI, however the URL is not allowing me to display the images on the page correctly.

You can use boto3 config to upload your images and that will not add http://localhost:8000/plants in your base url of image.
from storages.backends.s3boto import S3BotoStorage
class PublicMediaStorage(S3Boto3Storage):
location = "media"
default_acl = "public-read"
file_overwrite = False
custom_domain = False
and use the above class in your model using storage params of django model
class PlantImage(models.Model):
plant = models.ForeignKey(Plant, default=None, on_delete=models.CASCADE, related_name="plant_images")
images = models.ImageField(storage=PublicMediaStorage() ,upload_to = 'plant_images/')
def __str__(self):
return self.plant.name
