293

I'm trying to upload an image via the Django admin and then view that image either in a page on the frontend or just via a URL.

Note this is all on my local machine.

My settings are as follows:

MEDIA_ROOT = '/home/dan/mysite/media/'

MEDIA_URL = '/media/'

I have set the upload_to parameter to 'images' and the file has been correctly uploaded to the directory:

'/home/dan/mysite/media/images/myimage.png'

However, when I try to access the image at the following URL:

http://127.0.0.1:8000/media/images/myimage.png

I get a 404 error.

Do I need to setup specific URLconf patters for uploaded media?

Any advice appreciated.

Thanks.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Dan
  • 3,041
  • 2
  • 17
  • 9

18 Answers18

364

UPDATE for Django >= 1.7

Per Django 2.1 documentation: Serving files uploaded by a user during development

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

You no longer need if settings.DEBUG as Django will handle ensuring this is only used in Debug mode.


ORIGINAL answer for Django <= 1.6

Try putting this into your urls.py

from django.conf import settings

# ... your normal urlpatterns here

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

With this you can serve the static media from Django when DEBUG = True (when you run on local computer) but you can let your web server configuration serve static media when you go to production and DEBUG = False

Micah Carrick
  • 9,967
  • 3
  • 31
  • 43
  • 16
    PS. You can then use this in your templates: – Micah Carrick Apr 01 '11 at 19:45
  • I don't think it's good to add `^` sign before `media//(?P.*)$`, sometime when we access media file in app url path (like `http://127.0.0.1:8000/myapp/media/img/logo.png`), this regular won't math. – Jack Zhang Jul 25 '13 at 06:51
  • I've been struggling for 2 days now why my images return 404. This is the only thing I'm missing and I can't find it in Django doc. Thanks. – tambalolo Aug 12 '13 at 02:45
  • 1
    If you're using Django 1.5+, please see the answer below; it is a better solution. – Thane Brimhall Apr 06 '16 at 14:14
  • is this in your app or project urls.py? – user7804781 Feb 13 '18 at 16:07
  • Will this work outside debug mode? If not, do you know how it can be made to work? I plan to run the app locally only. – olfek Feb 29 '20 at 14:56
  • Ok, to answer my own question, see the following two answers. [one](https://stackoverflow.com/a/7639983) and [two](https://stackoverflow.com/a/60466558). – olfek Feb 29 '20 at 15:20
  • @MicahCarrick what is "document_root" and how does it work I'm getting document_root not defined. – Kennerdol Jun 25 '23 at 20:32
115

Please read the official Django DOC carefully and you will find the most fit answer.

The best and easist way to solve this is like below.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
JChen___
  • 3,593
  • 2
  • 20
  • 12
  • 2
    It is a new feature added in django 1.5 – codeVerine Jul 31 '13 at 11:38
  • is it ok to use it this way in production with apache? – andilabs Jan 28 '14 at 16:51
  • 1
    @andi - No its not okay to use it this way in production. It should be configured via apache on your production. – Vikas Gulati Mar 20 '14 at 10:22
  • 1
    In 1.7 https://docs.djangoproject.com/en/1.7/howto/static-files/#serving-files-uploaded-by-a-user-during-development – ErDmKo Nov 13 '14 at 06:41
  • 1
    But it's OK to leave this code here in production with no `if settings.DEV` check because it's disabled automatically? – jozxyqk Nov 01 '15 at 12:08
  • Just to follow up @jozxyqk 's comment, I understand that there is no need to use `if settings.DEBUG:` as the answer below, if the code will be used in production? – HBat Apr 25 '17 at 14:17
  • For **Django 2.0.***, check out the docs [here](https://docs.djangoproject.com/en/2.0/howto/static-files/#serving-files-uploaded-by-a-user-during-development). – Eje Jul 13 '18 at 04:50
77

For Django 1.9, you need to add the following code as per the documentation :

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

For more info, you can refer here : https://docs.djangoproject.com/en/1.9/howto/static-files/#serving-files-uploaded-by-a-user-during-development

thisisashwani
  • 1,748
  • 2
  • 18
  • 25
38

Here What i did in Django 2.0. Set First MEDIA_ROOT an MEDIA_URL in setting.py

MEDIA_ROOT = os.path.join(BASE_DIR, 'data/') # 'data' is my media folder
MEDIA_URL = '/media/'

Then Enable the media context_processors in TEMPLATE_CONTEXT_PROCESSORS by adding

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [],
    'APP_DIRS': True,
    'OPTIONS': {
        'context_processors': [
            #here add your context Processors
            'django.template.context_processors.media',
        ],
    },
},
]

Your media context processor is enabled, Now every RequestContext will contain a variable MEDIA_URL.

Now you can access this in your template_name.html

<p><img src="{{ MEDIA_URL }}/image_001.jpeg"/></p>
Akhilendra
  • 1,137
  • 1
  • 16
  • 31
24

Do I need to setup specific URLconf patters for uploaded media?

Yes. For development, it's as easy as adding this to your URLconf:

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

However, for production, you'll want to serve the media using Apache, lighttpd, nginx, or your preferred web server.

mipadi
  • 398,885
  • 90
  • 523
  • 479
7

If you'r using python 3.0+ then configure your project as below

Setting

STATIC_DIR = BASE_DIR / 'static'
MEDIA_DIR = BASE_DIR / 'media'
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'

Main Urls

from django.conf import settings
from django.conf.urls.static import static

urlspatterns=[
........
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
6

(at least) for Django 1.8:

If you use

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

as described above, make sure that no "catch all" url pattern, directing to a default view, comes before that in urlpatterns = []. As .append will put the added scheme to the end of the list, it will of course only be tested if no previous url pattern matches. You can avoid that by using something like this where the "catch all" url pattern is added at the very end, independent from the if statement:

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

urlpatterns.append(url(r'$', 'views.home', name='home')),
S. Ju.
  • 101
  • 2
  • 3
6

Here are the changes I had to make to deliver PDFs for the django-publications app, using Django 1.10.6:

Used the same definitions for media directories as you, in settings.py:

MEDIA_ROOT = '/home/user/mysite/media/'

MEDIA_URL = '/media/'

As provided by @thisisashwanipandey, in the project's main urls.py:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

and a modification of the answer provided by @r-allela, in settings.py:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                # ... the rest of your context_processors goes here ...
                'django.template.context_processors.media',
            ],
         },
    },
]
Alex Willison
  • 257
  • 7
  • 20
5

Another problem you are likely to face after setting up all your URLconf patterns is that the variable {{ MEDIA_URL }} won't work in your templates. To fix this,in your settings.py, make sure you add

django.core.context_processors.media

in your TEMPLATE_CONTEXT_PROCESSORS.

vishes_shell
  • 22,409
  • 6
  • 71
  • 81
r_allela
  • 792
  • 11
  • 23
5

Following the steps mentioned above for =>3.0 for Debug mode

urlpatterns = [
...
]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

And also the part that caught me out, the above static URL only worked in my main project urls.py file. I was first attempting to add to my app, and wondering why I couldn't see the images.

Lastly make sure you set the following:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Gavin
  • 632
  • 8
  • 10
3

This if for Django 1.10:

 if settings.DEBUG:
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2

Adding to Micah Carrick answer for django 1.8:

if settings.DEBUG:
  urlpatterns.append(url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}))
user3894045
  • 313
  • 3
  • 8
2

This is what I did to achieve image rendering in DEBUG = False mode in Python 3.6 with Django 1.11

from django.views.static import serve
urlpatterns = [
url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
# other paths
]
comiventor
  • 3,922
  • 5
  • 50
  • 77
2

On production environment Django does not load the media root automatically so that we can overcome that issue by adding following codes right after URL patterns:

urlpatterns = [
       ''''
         your urls
       ''''
    ] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL,
                              document_root=settings.MEDIA_ROOT)

If you are using more than one app and if you are including app urls on main app url, just add this code(configuration) on main project URL.

Madhav Dhungana
  • 476
  • 4
  • 13
1

Your setting is all right. Some web servers require to specify the media and static folder files specifically. For example in pythonanywhere.com you have to go to the 'Web' section and add the url od the media folders and static folder. For example:

  URL                     Directory                
/static/            /home/Saidmamad/discoverthepamirs/static     
/accounts/static/   /home/Saidmamad/discoverthepamirs/accounts/static    
/media/            /home/Saidmamad/discoverthepamirs/discoverthepamirs/media    

I know that it is late, but just to help those who visit this link because of the same problem ;)

Saidmamad
  • 63
  • 1
  • 13
1

Add this code below to "settings.py" to access(open or display)uploaded files:

# "urls.py"

from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
0

For Django 3.0+ in development have the below in your main urls.py:

urlpatterns = [
   # rest of your url paths here..
]

from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    urlpatterns += (
        static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +
        static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
        )
Nick
  • 51
  • 1
  • 3
0

Add this code in settings.py

urlpatterns = [ 

....

....


]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
TarangP
  • 2,711
  • 5
  • 20
  • 41