# Uploaded images from my Django model returning the literal string.

**URL:** <https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934>\
**Category:** Mystery Errors\
**Created:** [June 10, 2024, 12:35pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934 "2024-06-10T12:35:17Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![BlauweStadTechnologi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/blauwestadtechnologi/32/15959_2.png) [@BlauweStadTechnologi](https://forum.djangoproject.com/u/BlauweStadTechnologi)\
**Post date:** [June 10, 2024, 12:35pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/1 "2024-06-10T12:35:17Z")

</div>

This is a long one.

I have a Django model named `MediaModule` with an `ImageField()` within the model.

The `ImageField()` is configured in the following fashion:

`article_image = models.ImageField(upload_to='assets/')`

The above model is stored in a Django app named `media` and directory setup is configured in the following fashion:

`ROOT / media (app name) / assets / <image-name>`

My `settings.py` configuration in relation to the serving of images from within a Django model are as follows:

```auto
DEBUG = False

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'media',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    "whitenoise.middleware.WhiteNoiseMiddleware",
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

STORAGES = {

    'default': {
        'BACKEND': 'django.core.files.storage.FileSystemStorage',
    },

    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_DIRS = [BASE_DIR / "static",]

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

```

In my `<root>.urls`, file, I have the following:

```auto
from django.contrib import admin
from django.urls import path, include
from . import views
from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve

urlpatterns = [
    
    path('admin/', admin.site.urls),
    path('news/', include('media.urls')),

]

# Only for development. Do not use this in production.
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

```

in my `media.urls` file; the following is configured:

```auto
from django.urls import path, include
from . import views
from django.contrib import admin

urlpatterns = [
    path('articles/<str:article_identifier>', views.details),

]

```

In my `media.views` file, I have the following:

```auto
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.template import loader
from .models import MediaModule
from xxx import utils

def article_objects():
  '''This will create an instance of the model to obtain all values from the model. It will then return the name of the model instance.s'''
  articles = MediaModule.objects.all()
  return articles

def details(request, article_identifier):
    
  articles = article_objects()
  article = get_object_or_404(MediaModule,article_identifier=article_identifier)
  meta_object __image = utils.meta_object__ image(article.article_image.url)
  template = loader.get_template('media-article.html')

  context = {
      
    'article' : article,
    'articles' : articles,
    'meta_object __image' :	meta_object__ image,

    }
  
  return HttpResponse(template.render(context, request))

```

The relevant components of my `MediaModule` model from within `media.models` is as follows:

_The `generate_unique_number(char_length)` is a separate function which generates a random number which uniquely identifies a model object and appends it onto the URL, unrelated to the `article_image` issue but included for continuity. It’s actually pretty cool!_

```auto
from django.db import models

# Create your models here.
class MediaModule(models.Model):

    article_identifier = models.CharField(primary_key=True, max_length=50, default="generate_unique_number(12)", unique=True)
    article_image = models.ImageField(upload_to='assets/')

```

And lastly, from within my `media-article.html`, image is called in the following way:

`<img src="{{article.article_image.url}}" alt=""/>`

**Results**

1. Upon checking the browser console, there are 404 error messages for the images. Browser console returns `http://127.0.0.1:8000/media/assets/<image-name>.jpeg`

2. Inspecting the source `inspect source`, the image is being obtained from `/media/assets/<img name>`

3. All others images served from `staticfiles` have no issues with being shown.

4. I’m failing to see why my browser is failing to find the image, despite said image being being placed in the correct folder directory with the relative directory in my model being `upload_to="assets/"`.

5. From the web page, inspecting the source code, it only returns: `<img src="/media/assets/<image-name>" alt="">`

6. Further information: this is a development environment.

If anybody needs anything clarifying or anything I’ve missed out, let me know.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 10, 2024, 1:51pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/2 "2024-06-10T13:51:18Z")

</div>

Two quick questions/items to get started -

- is this a development environment (using ‘runserver’, or your production environment (perhaps using gunicorn or uwsgi)?

- Be aware that on a number of levels, media files are different from static files, and what works with one has no relevance on the other. (In other words, referring to your static files at all provides no diagnostic information regarding media files.)

---

<div class="post-metadata">

**Author:** ![BlauweStadTechnologi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/blauwestadtechnologi/32/15959_2.png) [@BlauweStadTechnologi](https://forum.djangoproject.com/u/BlauweStadTechnologi)\
**Post date:** [June 10, 2024, 4:00pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/3 "2024-06-10T16:00:01Z")

</div>

Thank you very much, it’s a development environment. I want to ensure that everything is working tickety-boo with `Debug` set to False before deploying to my existing Production server - which is using NGINX & Gunicorn.

I will update my post to include this information.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 10, 2024, 11:30pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/4 "2024-06-10T23:30:13Z")

</div>

> [@BlauweStadTechnologi](#):
>
> I want to ensure that everything is working tickety-boo with `Debug` set to False before deploying to my existing Production server - which is using NGINX & Gunicorn.

If that’s your objective, then I’d suggest you create a “staging” environment that replicates your production environment. The `runserver` development environment does _not_ handle static or media files in the same manner that your production environment does. Therefore, what you would do with your configuration to make this work in `runserver` does not mean that your production environment will work - and vice versa.

---

<div class="post-metadata">

**Author:** ![BlauweStadTechnologi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/blauwestadtechnologi/32/15959_2.png) [@BlauweStadTechnologi](https://forum.djangoproject.com/u/BlauweStadTechnologi)\
**Post date:** [June 13, 2024, 9:41am UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/5 "2024-06-13T09:41:11Z")

</div>

Yes, I am aware that production and development environments handle these sorts of things differently, and that when `DEBUG` is set to `False`, all static files are handler by a central `staticfiles` folder.

All other static files that are NOT uploaded to a model show with no issues, the website is up and running & the only images that refuse to show are the images which are in the models and are being called by `article.article_image.url`.

It’s like it has some sort of vendetta against the images uploaded to models.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 13, 2024, 12:10pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/6 "2024-06-13T12:10:01Z")

</div>

> [@BlauweStadTechnologi](#):
>
> All other static files that are NOT uploaded to a model show with no issues,

- The way you’ve phrased this leads me to believe that you are still thinking of “media files” as if they were just a different type of static file. They are not. There is no such thing as a “static file uploaded to a model.” If a file is uploaded, it is not a static file.

- You are using the `whitenoise` app to handle static files. This app has nothing to do with media files, that’s why there’s the difference in behavior.

- In your urls, you have:

> [@BlauweStadTechnologi](#):
>
> ```auto
> if settings.DEBUG:
> urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
> urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
> 
> ```

Since you’re setting DEBUG = False, these url patterns are not being added. Django isn’t going to know how to handle static or media urls when DEBUG = False. You’ve added the third-party “whitenoise” app to handle the static files, but nothing is set to handle the media files. You need to move the media url settings out of the `if` statement for Django to handle them.  
(Note, you will want to move that back into the if when you deploy to production, because in a proper deployment environment, Django won’t be needed to handle _either_ type of file. That’s why I recommend setting up a staging environment to test running your system with DEBUG = False. Using runserver with DEBUG = False tends to create more problems than they resolve.)

---

<div class="post-metadata">

**Author:** ![BlauweStadTechnologi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/blauwestadtechnologi/32/15959_2.png) [@BlauweStadTechnologi](https://forum.djangoproject.com/u/BlauweStadTechnologi)\
**Post date:** [June 14, 2024, 8:31am UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/7 "2024-06-14T08:31:48Z")

</div>

> [@BlauweStadTechnologi](#):
>
> ```auto
> if settings.DEBUG:
> urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
> urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
> 
> ```

Yes, so if `DEBUG` is set to `False`, the above will not apply. If `DEBUG is set to `True`, the above will apply.

Therefore, just to clarify what you are saying, I will need to alter the above to:

```auto
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

```

This means that regardless as to the setting of `DEBUG`, all `MEDIA` files will be handled in the same way, where as the `STATIC` files will be handled either by the local `static` folders in the respective app, or via the centralized `STATIC_URL` file.

I will also take on board your recommendation over the creating a stating environment, however, just needing to get me head around this and taking one step at a time.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 14, 2024, 11:14am UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/8 "2024-06-14T11:14:37Z")

</div>

You are correct, with the additional clarification that this change should _only_ be made when you’re using runserver with DEBUG = False. When you’re ready to move this to your production environment, you’ll want to move it back.

---

<div class="post-metadata">

**Author:** ![BlauweStadTechnologi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/blauwestadtechnologi/32/15959_2.png) [@BlauweStadTechnologi](https://forum.djangoproject.com/u/BlauweStadTechnologi)\
**Post date:** [June 17, 2024, 12:32pm UTC](https://forum.djangoproject.com/t/uploaded-images-from-my-django-model-returning-the-literal-string/31934/10 "2024-06-17T12:32:05Z")

</div>

Thank you. Seeing as am now wanting to source `media` images from an external source (Azure Blogs). I have the following setup

```auto
pip install django-storages 
pip install azure-storage-blob

```

```auto
#settings.py
from . import custom_storage
DEBUG = True
STORAGES = {

    'default': {
                'BACKEND': os.environ.get('blauwestadtech.custom_storage.CustomAzureStorage', 'django.core.files.storage.FileSystemStorage')

    },

    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

AZURE_ACCOUNT_NAME = 'xxx'
AZURE_ACCOUNT_KEY = 'xxxx' 
AZURE_CONTAINER = 'assets'  
AZURE_CUSTOM_DOMAIN = f'{AZURE_ACCOUNT_NAME}.blob.core.windows.net'

if DEBUG:
    # This setting is only used during development with the Django development server
    MEDIA_URL = '/media/'
    MEDIA_ROOT = BASE_DIR / 'media'
else:
    MEDIA_URL = f'https://{AZURE_CUSTOM_DOMAIN}/'

```

```auto
#custom_storage.py
from django.conf import settings
from storages.backends.azure_storage import AzureStorage

class CustomAzureStorage(AzureStorage):
    def __init__ (self, *args, **kwargs):
        self.account_name = settings.AZURE_ACCOUNT_NAME
        self.account_key = settings.AZURE_ACCOUNT_KEY
        self.azure_container = settings.AZURE_CONTAINER
        self.expiration_secs = None # Set expiration time for the URLs if needed
        super(). __init__ (*args, **kwargs)

```

```auto
#urls.py
if settings.DEBUG:
    #urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    #urlpatterns += [re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT, }),]
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

```

```auto
#models.py
from django.conf import settings
def upload_to():
    return f"{settings.AZURE_CONTAINER}/"
def upload_to():
    return f"{settings.AZURE_CONTAINER}/"

class Blog(models.Model):
    BlogImage = models.ImageField(default="",upload_to=upload_to(), verbose_name="Blog Image")

```

With this set up in mind, why is Django constructing the blob image URL by putting the `AZURE_CONTAINER` name in twice? The URL is constructed in the following manner:

`https://<AZURE_ACCOUNT_NAME>.blob.core.windows.net/assets/assets/` when it should be:  
`https://<AZURE_ACCOUNT_NAME>.blob.core.windows.net/assets/`

I have even hard coded the `upload_to` variable with `upload_to="assets/"` but Django still incorrectly constructs the URL by duplicating the `<AZURE_CONTAINER>`. Every change I make is completely ignored, despite development server refreshes and changing the `DEBUG` from `True` to `False` and back again.

I just do not understand the logic Django is using to justify returning the blog URL in this way.

I just don’t understand why Django is incorrectly construing the URL here.
