Accessing "Media" files in Django

Viewed 101018

I'd like to love Django, but this business of static and media files in development environments is driving me nuts. Please rescue me from my stupidity.

I'm on my development machine. I have folder media in the root of my project directory.

In settings.py I have: MEDIA_ROOT = '' and MEDIA_URL = '/media/'.

In urls.py I have:

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$',
            'django.views.static.serve',
            {'document_root': settings.MEDIA_ROOT, }),
    )

But the only way I can get media files is by referencing /media/media/ e.g. <img src="/media/media/image.png" />.

I expect (and want)
<img src="/media/image.png" />

Can anyone tell me what is happening here, and give me a simple recipe for setting up media file handling?

Thank you very much.


@Timmy O'Mahony - thanks! epic post, and very clear. But it leaves a couple of questions:

(1) I have to use /media/ and /static/, not media/ and static/ as MEDIA_URL and and STATIC_URL - am I missing something?

(2) If collectstatic hoses /static/, where do you put site level CSS e.g. the site's CSS files? Not in /static/, evidently.

(3) I put them in a directory '_' off the project root and set STATICFILES_DIRS to point to it - and that seems to be where the development server gets its static files, despite the urlpatterns directive. If THAT is wrong, where do you put site level CSS during development, and what is the workflow around collectstatic when you modify them - do you have to edit them one place, and collect them someplace else after every edit?

8 Answers

For Django version 3 I used the following:

from django.conf import settings
from django.urls import re_path
from django.views.static import serve

# ... the rest of your URLconf goes here ...

if settings.DEBUG:
    urlpatterns += [
        re_path(r'^media/(?P<path>.*)$', serve, {
            'document_root': settings.MEDIA_ROOT,
        }),
    ]

my settings.py

BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
STATIC_URL = '/static/'

here is a documentation link https://docs.djangoproject.com/en/3.1/ref/views/ In case you are using Django REST with some dev server don't forget to update your dev proxy settings to redirect /media to Django backend

Here is another alternative:

Set your media configs something like this inside 'settings.py':

#Set media path
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'

Lets say I have a modal called person with image filed like below:

class Person(models.Model):
    name = models.CharField(max_length = 30)
    photo = models.ImageField(upload_to = 'photos')

Now here upload_to path we are taking about is inside the MEDIA_ROOT folder. In my case a media folder will be created inside which photos folder will be created and our media here will be dumped.

So now in my template I do something like this:

<img src="{{ person.photo.url}} />

So in short, you got a field, use it like this:

src ={{ object.field.url}}

Hope that helps! Happy Coding!

Related