antpngl92
antpngl92

Reputation: 534

Django Uploaded images not displayed in production

I am aware of this question: Django Uploaded images not displayed in development , I have done everything that it is described, but still can't find a solution. I also have used for reference this: GeeksForGeeks and Uploaded Files and Uploaded Handlers - Django documentation, however, none of them solved my problem.

I have deployed a Django App on a Ubuntu server for the first time using Nginx and gunicorn. Before deployment, I used port 8000 to test if everything runs as it is supposed to and all was fine. Since I allowed 'Nginx Full' my database images are not showing up.

This is my django project structure:

project structure

My virtual environment folder and my main project folder are both in the same directory. I have separated them.

# Create your models here.
class Project(models.Model):
    project_name = models.CharField(max_length=120)
    project_description = models.CharField(max_length=400)
    project_link = models.CharField(max_length=500)
    project_image = models.ImageField(upload_to='')

    def __str__(self):
        return self.project_name

I have set up my settings.py to :

# 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_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')


MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), '..', 'media').replace('\\','/')

My view gets all the project object from a database and passes those to the template. The template renders successfully all other information related to project model except the image field . In my template I do:

 <div class="row text-center mx-auto">

        {% for project in projects %}
        {% if forloop.counter|mod:2 == 0 %}
        <div class="col projects pb-3 pt-3 mb-3 ml-2">
          {% else %}
          <div class="col projects pb-3 pt-3 mb-3 mr-2">
            {% endif %}

            <img class="card-img-top pt-2 pl-2 pr-2" src="{{ project.project_image.url}}"
              alt="Image could not be found :(" style="height:120px; width:166px !important;" /><br>
            <div class="card-body">
              <h3 class="card-title ">{{ project.project_name }}</h3>
              <p class="card-text dates">{{ project.project_description}}</p>
              <a href="{{ project.project_link }}" class="btn btn-dark" target="_blank">Link</a>

            </div>
          </div>

          {% if forloop.counter|mod:2 == 0 %}
          <div class="w-100"></div>
          {% endif %}
          {% endfor%}
        </div>
      </div>

Uploading the images works, it sends them in the project's media directory, the problem is that they are not showing up, the alt="" is activated.

My main urls.py:

urlpatterns = [
     path('', include('project.urls')),
    path('admin/', admin.site.urls),
]  + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

The gunicorn system file:


[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=myusername
Group=www-data
WorkingDirectory=/home/myusername/myproject
ExecStart=/home/myusername/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myusername/myproject/myproject.sock myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Nginx setup:

  server {
        listen 80;
        server_name <my IP> ;
        location = /favicon.ico { access_log off; log_not_found off; }
        location /static/ {
            root /home/myusername/myproject;
        }
        location / {
            include proxy_params;
            proxy_pass http://unix:/home/myusername/myproject/myproject.sock;
        }
    }

EDIT: When inspecting the image element of the webpage the source of the image it is "/media/imageNmae.png". Any help would be appreciated!

EDIT: The solution has been found, the Nginx was not serving the media as Daniel suggested. There is some uWSGI documentation which is worth reading to avoid further similar problems Documentation

Upvotes: 3

Views: 2088

Answers (2)

Divyanshu Parihar
Divyanshu Parihar

Reputation: 26

You may need to run this command : python manage.py collectstatic from the shell of your platform if you are using heroku here is the command

heroku run python manage.py collectstatic

Upvotes: 0

Daniel Hepper
Daniel Hepper

Reputation: 29967

Your Nginx is not serving the MEDIA_URL i.e. /media/. You need an Nginx configuration section like you have for /static/

  server {
        listen 80;
        server_name <my IP> ;
        location = /favicon.ico { access_log off; log_not_found off; }
        location /static/ {
            root /home/myusername/myproject;
        }
        location /media/ {
            root /home/myusername/myproject;
        }
        location / {
            include proxy_params;
            proxy_pass http://unix:/home/myusername/myproject/myproject.sock;
        }
    }

Upvotes: 7

Related Questions