Django MEDIA_URL i MEDIA_ROOT

229

Próbuję załadować obraz za pośrednictwem administratora Django, a następnie wyświetlić ten obraz na stronie w interfejsie lub po prostu za pomocą adresu URL.

Pamiętaj, że to wszystko na moim komputerze lokalnym.

Moje ustawienia są następujące:

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

MEDIA_URL = '/media/'

Ustawiłem parametr upload_to na „images”, a plik został poprawnie przesłany do katalogu:

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

Jednak gdy próbuję uzyskać dostęp do obrazu pod następującym adresem URL:

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

Otrzymuję błąd 404.

Czy muszę skonfigurować określone wzorce URLconf dla przesłanych multimediów?

Wszelkie porady są mile widziane.

Dzięki.

Dan
źródło

Odpowiedzi:

293

AKTUALIZACJA dla Django> = 1,7

Dokumentacja według Django 2.1: Udostępnianie plików przesłanych przez użytkownika podczas programowania

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)

Nie musisz już, if settings.DEBUGponieważ Django zajmie się tym, aby zapewnić, że jest to używane tylko w trybie debugowania.


ORYGINALNA odpowiedź dla Django <= 1.6

Spróbuj umieścić to w swoim 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}))

Dzięki temu możesz obsługiwać nośniki statyczne z Django, kiedy DEBUG = True(kiedy działasz na komputerze lokalnym), ale możesz pozwolić konfiguracji serwera WWW obsługiwać nośniki statyczne, gdy przejdziesz do produkcji iDEBUG = False

Micheasz Carrick
źródło
14
PS. Następnie możesz użyć tego w swoich szablonach: <img src = "{{MEDIA_URL}} images / myimage.png" />
Micah Carrick
Nie sądzę, że dobrze jest dodawać ^znak wcześniej media//(?P<path>.*)$, kiedyś, gdy uzyskujemy dostęp do pliku multimedialnego na ścieżce adresu URL aplikacji (jak http://127.0.0.1:8000/myapp/media/img/logo.png), ta zwykła matematyka nie będzie.
Jack Zhang,
Walczę od 2 dni, dlaczego moje obrazy zwracają 404. To jedyna rzecz, za którą tęsknię i nie mogę jej znaleźć w dokumencie Django. Dzięki.
tambalolo,
1
Jeśli używasz Django 1.5+, zapoznaj się z odpowiedzią poniżej; to lepsze rozwiązanie.
Thane Brimhall
czy to jest w twojej aplikacji lub projekcie urls.py?
user7804781,
105

Proszę uważnie przeczytać oficjalny Django DOC, a znajdziesz najbardziej odpowiednią odpowiedź.

Najlepszym i najłatwiejszym sposobem rozwiązania tego jest jak poniżej.

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)
JChen___
źródło
1
Jest to nowa funkcja dodana w django 1.5
codeVerine
czy można używać go w ten sposób w produkcji z apache?
andilabs
1
@ andi - Nie, nie można używać go w ten sposób w produkcji. Powinien zostać skonfigurowany za pomocą apache na twojej produkcji.
Vikas Gulati
1
Ale czy można pozostawić ten kod w produkcji bez if settings.DEVsprawdzania, ponieważ jest on wyłączany automatycznie?
jozxyqk
70

W przypadku Django 1.9 należy dodać następujący kod zgodnie z dokumentacją:

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)

Więcej informacji można znaleźć tutaj: https://docs.djangoproject.com/en/1.9/howto/static-files/#serving-files-uploaded-by-a-user-during-development

thisisashwani
źródło
2
To jest rozwiązanie dla django> 1.9, dzięki.
unixeO
13
Pamiętaj tylko, aby umieścić to w urls.py twojego projektu, a nie aplikacji, co przypadkowo zrobiłem.
Jarno
3
Pracowałem również dla 1.10.
Deleet,
nie działa dla mnie Być może w pliku settings.py są jakieś niezbędne ustawienia podstawowe?
Fusion
25

Oto, co zrobiłem w Django 2.0. Ustaw pierwszy MEDIA_ROOT na MEDIA_URL wsetting.py

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

Następnie włączyć media context_processors w TEMPLATE_CONTEXT_PROCESSORSdodając

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

Twoja media context processorjest włączona, teraz każda RequestContextbędzie zawierać zmienną MEDIA_URL.

Teraz możesz uzyskać do tego dostęp w swoim template_name.html

<p><img src="{{ MEDIA_URL }}/image_001.jpeg"/></p>
Achilendra
źródło
wspaniale wyjaśnione - to była dla mnie odpowiedź. Kluczem było dodanie procesora kontekstu medialnego .
David Maness,
23

Czy muszę skonfigurować określone wzorce URLconf dla przesłanych multimediów?

Tak. W przypadku programowania jest to tak proste, jak dodanie tego do URLconf:

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

Jednak w przypadku produkcji będziesz chciał obsługiwać media za pomocą Apache, lighttpd, nginx lub preferowanego serwera WWW.

mipadi
źródło
3
Co to znaczy, jak skonfigurować serwer?
M Hornbacher,
Dostaję nierozwiązane odniesienie do „wzorów”, czy jest to importowane skądś?
user7804781,
6

(przynajmniej) dla Django 1.8:

Jeśli użyjesz

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

jak opisano powyżej, upewnij się, że żaden wzorzec adresu URL „catch all”, kierujący do domyślnego widoku, nie jest wcześniejszy niż w urlpatterns = []. Ponieważ .append umieści dodany schemat na końcu listy, zostanie on oczywiście przetestowany tylko wtedy, gdy żaden poprzedni wzorzec adresu URL nie pasuje. Można tego uniknąć, stosując coś takiego, w którym wzorzec adresu URL „catch all” jest dodawany na samym końcu, niezależnie od instrukcji if:

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.
źródło
6

Oto zmiany, które musiałem wprowadzić, aby dostarczyć pliki PDF dla aplikacji django-publications przy użyciu Django 1.10.6:

Używasz tych samych definicji dla katalogów multimediów jak Ty, w settings.py:

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

MEDIA_URL = '/media/'

Jak zapewnia @thisisashwanipandey, w głównej części projektu 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)

oraz modyfikacja odpowiedzi udzielonej przez @ r-allela w 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
źródło
4

Kolejnym problemem, z którym możesz się spotkać po skonfigurowaniu wszystkich wzorców URLconf, jest to, że zmienna {{ MEDIA_URL }}nie będzie działać w twoich szablonach. Aby to naprawić, w pliku settings.py upewnij się, że dodajesz

django.core.context_processors.media

w twoim TEMPLATE_CONTEXT_PROCESSORS.

r_allela
źródło
2

Dodanie do odpowiedzi Micheica Carricka dla django 1.8:

if settings.DEBUG:
  urlpatterns.append(url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}))
użytkownik3894045
źródło
1
Nie działa dla mnie (1.10). TypeError: view must be a callable or a list/tuple in the case of include()..
Deleet,
2

Tak zrobiłem, aby uzyskać renderowanie obrazów w trybie DEBUG = False w Pythonie 3.6 z Django 1.11

from django.views.static import serve
urlpatterns = [
url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
# other paths
]
współtwórca
źródło
2

Postępując zgodnie z krokami wymienionymi powyżej dla => 3.0 dla trybu debugowania

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

A także część, która mnie złapała, powyższy statyczny adres URL działał tylko w moim głównym pliku urls.py projektu. Najpierw próbowałem dodać do mojej aplikacji i zastanawiałem się, dlaczego nie widziałem obrazów.

Na koniec upewnij się, że ustawiłeś:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Gavin
źródło
1

Dzieje się tak, jeśli dla Django 1.10:

 if settings.DEBUG:
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Jose Luis Quichimbo
źródło
0

Twoje ustawienie jest w porządku. Niektóre serwery WWW wymagają szczególnego określenia plików folderów multimedialnych i statycznych. Na przykład w pythonanywhere.com musisz przejść do sekcji „Web” i dodać adres URL folderów multimediów i folderu statycznego. Na przykład:

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

Wiem, że jest późno, ale tylko po to, aby pomóc tym, którzy odwiedzają ten link z powodu tego samego problemu;)

Saidmamad
źródło