2

The images i upload through the admin-interface i production cannot be found, though it exists on the server.It loads fine in development. I use Django Image-kit to resize the uploaded image.

The image isn't displayed on the website and if i follow the image url, I get

<h1>Not Found</h1>
<p>The requested URL /media/CACHE/images/references/<reference-name>/<image-name>/211b0022f8a2baad7cdc527711dcb.jpg was not found on this server.</p>

The uploaded image is not added to my static files, which are correctly displayed.

My model looks like this:

def generate_unique_slug(instance, field):
    original = slugify(field)
    unique = original
    numb = 1
    while instance.objects.filter(slug=unique).exists():
        unique = f'{original}-{numb}'
        numb += 1
    return unique

def reference_main_image_path(instance, filename):
    sub_folder = instance.slug
    return f'references/{sub_folder}/{filename}'

class Reference(models.Model):
    title = models.CharField(max_length=60)
    description = models.TextField(max_length=2000)
    slug = models.SlugField(max_length=12, unique=True, blank=True)
    main_image = models.ImageField(
        upload_to=reference_main_image_path, default='default.png')
    main_thumbnail = ImageSpecField(source='main_image',
                                processors=[ResizeToFill(540, 300)],
                                format='JPEG',
                                options={'quality': 80},)
    tags = TaggableManager()

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if self.slug:
            if slugify(self.title) != self.slug:
                self.slug = generate_unique_slug(Reference, self.title)
        else:
            self.slug = generate_unique_slug(Reference, self.title)
        super().save(*args, **kwargs)

My view.py:

def reference(request):
    context = {
        'references': Reference.objects.all(),
    }
    return render(request, 'home/references.html', context)

In the ´html` code I 'call' the image like this:

<img src="{{ reference.main_thumbnail.url }}"> 

My settings.py static and media variables look like this:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

I've run manage.py collectstatic

Should my upload_to in the be changed? Or how do I tell Django to look in the folder when 'collecting static' and then change the html to look in the static folder?

It seems weird to me that the documentation of image-kit should only regard 'development' or am I missing something?

Thank you!

Edit: I'm using gunicorn and Nginx in production, but as stated, my static files er loaded just fine.

Edit 2: Nginx conf:

server {
    server_name <server_names>;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/<user>/projects/<project>/<project>;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

I left out some certbot SSL configuration.

Edit 3:urls.py:

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


urlpatterns = [
    path('', views.home, name='home'),
    path('ydelser/', views.service, name='service'),
    path('referencer/', views.reference, name='reference'),
    path('kontakt/', views.contact, name='contact'),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Morten
  • 159
  • 1
  • 12
  • 1
    So you're not actually serving media files with nginx. Add appropriate location into nginx conf or (if you still want to serve media _always_ with django) show url.py where media urls are included. – Ivan Starostin Mar 04 '19 at 11:16
  • Thank you very much for helping me Ivan. I'm very new to this, obviously. I thought that with the Nginx line `location /static/ ...` I'd serve the media-files with nginx. I thought some Django-magic would move the admin-uploaded image to my static folder during `collectstatic` and Nginx would serve those files. How would I go about adding the uploaded file to my `/statics/` folder? Again, thank you. – Morten Mar 04 '19 at 11:26

1 Answers1

4

To serve media files with nginx you should add appropriate location similarly to static:

location /static/ {
    root /home/<user>/projects/<project>/<project>;
}

location /media/ {
    root /home/<user>/projects/<project>/<project>;
}

just like you did it in django:

...
STATIC_URL = '/static/'
...
MEDIA_URL = '/media/'

However, if you don't want to serve media files with nginx (which is recommended) and still want to server them with django (which is not recommended) then make sure that line

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

is enabled when DEBUG=False.

Note, you shouldn't treat media files as static - they are logically different. Whilst static files belong to and are shipped with your solution/project, media files are not part of your project and usually are produced by users.

ps

if you've uploaded some files into your website locally, then they are located accordingly to this:

def reference_main_image_path(instance, filename):
    sub_folder = instance.slug
    return f'references/{sub_folder}/{filename}'

class Reference(models.Model):
    ...
    main_image = models.ImageField(
        upload_to=reference_main_image_path, default='default.png')

If you did not copy them (files located on hard drive within folder configured above) to prod server - they will not show up. Copy them manually if needed and match destination folder with nginx location.

Ivan Starostin
  • 8,798
  • 5
  • 21
  • 39
  • 2
    Thank you so much Ivan, I'm continuously awed by the helpfulness of this community. The time people take to help others. I definitely wanted to serve the media files with nginx and I agree with your point of not treating media files as static files, my media files might very well change. I added the `location /media/` line to my nginx configuration file and the image is served as expected. Again, thank you! – Morten Mar 04 '19 at 14:27