Chris
Chris

Reputation: 459

Django - Serving user uploaded media files

I'm trying to display the media file(image) on the template of a DetailView.

I ran print statements to check where the MEDIA_ROOT and MEDIAFILES_DIRS are pointing, and they both point correctly to /project/static/media.

So I try to call it on the html page by using <img src="{{ object.profile_pic.url }}" /> , but it's not displaying.

I check the console, and it is looking for the file in XXX.X.X.X:8000/media/image_file.jpg.

Is it something to do with my MEDIA FILES setup in settings.py?

This is how my folder structure looks

/project
  /project
    /project
       urls.py (base)
    /apps
      /app1
        urls.py
    manage.py
  /static
    /media
      image_file.jpg

settings.py

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(os.path.dirname(BASE_DIR), "static", "static_files"),
]

STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static", "static_root")

"""
MEDIA FILES
"""
MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static", "media")

MEDIAFILES_DIRS = [
    os.path.join(os.path.dirname(BASE_DIR), "static", "media"),
]

"""
Override the BaseUser model
"""
AUTH_USER_MODEL = 'accounts.User'

urls.py // need to add the +static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) to the base urls.py, not the app-level

from django.conf.urls import include, url
from django.contrib import admin
from . import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [

    url(r'^$', views.HomepageTemplateView.as_view(), name='home'),
    url(r'^how-it-works/$', views.HowItWorksTemplateView.as_view(), name='how-it-works'),
    url(r'^categories/', include('apps.categories.urls')),
    url(r'^tasks/', include('apps.tasks.urls')),
    url(r'^accounts/', include('apps.accounts.urls')),
    url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

detailview.html

{% extends 'base.html' %}

{% block navbar %}
<div class="row">
    <div class="container">
        {% include 'navbar.html' %}
    </div>
</div>
{% endblock %}

{% block content %}
<div class="row">
    <div class="container">
        <div class="col-md-12">
            {% load staticfiles %}
            <p><img src="{{ object.profile_pic.url }}" /></p>

            <p>{{ object.username }}</p>
            <p>{{ object.first_name }} {{ object.last_name }}</p>
            <p>{{ object.email }}</p>
            <p>{{ object.contractorprofile.subcategory }}</p>
        </div>
    </div>
</div>

{% endblock %}

Upvotes: 1

Views: 4161

Answers (1)

JCotton
JCotton

Reputation: 11760

You added the static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) line to the urls.py of a specific app, i.e. not the base level urls.py. The base level will include the app-specific urls appending them to some stem. If the base urls.py has something like this, url(r'^apps/', include('apps.app1.urls')), then point your browser to server:8000/apps/media/image_file.jpg.

That's not what you want, so move the static() MEDIA_URL call to the base, project-level urls.py.

Let me mention a couple other things. Your folder structure puts media/ under static/; that's pretty confusing. You also included the settings for STATIC and MEDIA. Static files and media files are completely separate (often mixed up) topics. Static files are used by your code. Static files are the CSS, JavaScript, images, etc that your application needs. Media files are assets—images, documents, etc—that accrue through use of the application. profile_pic in your case is a perfect example of media; it's something a user uploaded. So nesting your media directory under static/ is conflating two independent things. Don't do it.

Another thing, you don't need {% load staticfiles %} in the template. That's used for staticfile-provided templatetags like {% static ...%} which you aren't using. Anyway, you should load templatetags at the top of the file to keep things clean.

Upvotes: 4

Related Questions