4 votes

Serving images as static files in Django

I have a problem with the deployment of an image, using the static tag.

I have a class called ProfileView which comes into action when I start session in my login form. This class examines the profile data of the user is to start session and display them in your home, data, such as name, username, photo, among others.

class ProfileView(LoginRequiredMixin, TemplateView):
    template_name = 'profile.html'

    def get_context_data(self, **kwargs):
        self.request.session['Hi'] = True
        context = super(ProfileView, self).get_context_data(**kwargs)
        is_auth = False
        name = None
        #Pregunto si en el request va el user
        user = self.request.user

        #Indago sobre los posibles casos, falta hacer cuando un user sea paciente y medico
        if user.is_medical:
        #if self.request.user.is_authenticated():
            print (user.is_medical)
            is_auth = True
            profile=user.get_medical_profile()
            #name = self.request.user.username

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }

            context.update({'userprofile':profile, 'data':data})
        elif user.is_patient:
            print (user.is_patient)
            is_auth=True
            profile=user.get_patient_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        elif user.is_physiotherapist:
            print (user.is_physiotherapist)
            is_auth=True
            profile=user.get_physiotherapist_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        return  context

    def get_userprofile(self):
        return self.request.user.userprofile

My configuration settings is the following:

I have a settings called base.py where in relation to the static files I have the following (it is Not the policy of DEBUG in this settings/base.py):

Usually I say here that my static files are going to be centralized in a directory called static thanks to the policy of STATIC_URL='/static/'

And after, STATICFILES_DIRS I'm saying to look for static files inside a directory called static so in every application or in the main application created by Django when you create the project.

# settings/base.py
import os

# 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/'

# With this configuration, Django will look for static files in a folder named static inside each app and into the neurorehabilitation/static folder created.
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

And I have a settings called development.py that inherits from base.py and that has this configuration: Note that I have the DEBUG=TRUE in this settings/development.py

I've read that the DEBUG must be in False when you want to cache static files, although I do not know if also when you want to serve them from the development environment.

Also in this settings/development.py I have a directive called MEDIA_ROOT , by means of which I tell Django that when I upload a file, it is saved in a directory called "media".

And the directive MEDIA_URL indicates that the files (images, sound, video) are going to be served from that url, /media/

# settings/development.py
from .base import *

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': get_env_variable('DATABASE_NAME'),
        'USER': get_env_variable('DATABASE_USER'),
        'PASSWORD': get_env_variable('DATABASE_PASSWORD'),
        'HOST': 'localhost',
        'PORT': '5433',
    }
}

MEDIA_URL = '/media/'

#Cuando suba los archivos de media (imagenes sonido, video), van a servirse
#desde ese url.    
MEDIA_ROOT = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-2] + ['media'])
#Ahí le estamos diciendo que donde este, en la carpeta media, cree los
#elementos. Esto creara una carpeta media en el proyecto cuando subamos
#un archivo+

In my template profile.html I'm calling the image by means of the invocation of the attribute photo which is a field of type ImageFieldwhich goes to the template thanks to the view previously shown as sent in the context.

It is within the label figure when I intend to call the image this way:

{% load static from staticfiles  %}



Here's all the content of my template profile.html

{% extends 'base.html' %}
<!-- {% load staticfiles  %} -->
{% block content %}
    <div>
        {% if userprofile %}
            {{ userprofile.user.username }}, <a href="{% url 'logout' %}">Logout</a>
        {% else %}
            <a href="">Login</a>
        {% endif %}
    </div>
            <div style="  ">
                <figure style=" ">
                    {% load static from staticfiles  %}
                    <img src="{% static '/media/{{ userprofile.user.photo }}' %}" alt="{{ userprofile.user.username }}">

                    <!-- <img src="/media/{{ userprofile.user.photo }}" alt="{{ userprofile.user.username }}"> -->

                    <figcaption>{{ userprofile.user.first_name }}</figcaption>
                    <!-- User esta relacionado 1 a 1 con userprofile model, por transitividad se llega
                     al campo username del modelo user desde userprofile-->
                </figure>

            </div>
{% endblock content %}

And that is how I get in my browser that the image does not appear, but the information related to the name, and the username of the user who newly logs

introducir la descripción de la imagen aquí

In my server log from Django I get this:

[28/Dec/2015 08:14:58] "GET /accounts/profile/ HTTP/1.1" 200 5467
Not Found: /media/{{ userprofile.user.photo }}
[28/Dec/2015 08:14:58] "GET /media/%7B%7B%20userprofile.user.photo%20%7D%7D HTTP/1.1" 404 1885

When I call the image without using the tag static but the traditional way is to say this:

<img src="/media/{{ userprofile.user.photo }}" alt="{{ userprofile.user.username }}">

There goes the image that I want to call.

What configuration I might be missing? Or what I may be ignoring or overlooking?

Anyway something that I plan to do in a short time is to centralize my files with collectstatic and put them in a CDN, Amazon S3 or from NGINX on a server. But for the moment in development I would like to work with them as well.

I don't know what can be faltándome.

9voto

César Points 14430

When you want to show files uploaded by the users you have to use the attribute url the file, something like this:

<img src="{{ userprofile.user.photo.url }}" alt="{{ userprofile.user.username }}">

Don't confuse the static with media, the first served for your JavaScript files, CSS, etc; the second serves for the files uploaded by the users. That said, it is not necessary to use {% load static from staticfiles %}.

If you have set correctly the path in which the files are uploaded, it makes no sense to use /media/ on the route, even if this were correct, you are going against the DRY as this is already defined in your settings, the correct thing would be to use {{ MEDIA_URL }}.

HolaDevs.com

HolaDevs is an online community of programmers and software lovers.
You can check other people responses or create a new question if you don't find a solution

Powered by:

X