Django | joined path is located outside of the base path component {% static img.thumbnail.url %}, Error 400 with whitenoise

ε祈祈猫儿з 提交于 2019-12-07 01:56:55

问题


I've finish my first app in Django and works perfectly, but still have pre-deployment problems since I set DEGUG=False ... Here is just to display an image in a template... T_T

I was using this, but now it does'nt work when I use whitenoise to serve my image localy... And it return a Bad Request(400) error...

Models.py

class GalleryItem(models.Model):
    thumbnail = models.ImageField(blank=True,upload_to='gallery/thumb')
    img_wide = models.ImageField(blank=True,upload_to='gallery')

template.py

{% load staticfiles %}
{% for img in img_to_display %}
    <a href="{{ img.img_wide.url}}" class="swipebox" title="">
        <img src="{% static img.thumbnail.url %}" alt="{{ img.alt}}">
    </a>
{% endfor %}

urls.py

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

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

urlpatterns = [
    url(r'^gallery/', include('gallery.urls')),
    url(r'^shop/', include('shop.urls')),
    url(r'^events/', include('events.urls')),
    url(r'^page/', include('paginator.urls')),
    url(r'^news/', include('blog.urls')),
    url(r'^ckeditor/', include('ckeditor_uploader.urls')),
    url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py

import os
import dj_database_url

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
print("BASE_DIR = ",BASE_DIR)
MEDIA_ROOT = os.path.join(BASE_DIR, 'wt/static/media/')
MEDIA_URL = '/media/'

SECRET_KEY = 'SECRET_KEY'

DEBUG = False

INSTALLED_APPS = [
    'ckeditor',
    'ckeditor_uploader',
    'team.apps.TeamConfig',
    'gallery.apps.GalleryConfig',
    'shop.apps.ShopConfig',
    'events.apps.EventsConfig',
    'blog.apps.BlogConfig',
    'paginator.apps.paginatorConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

ROOT_URLCONF = 'wt.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                "django.contrib.auth.context_processors.auth",
                "django.core.context_processors.request",
                "django.core.context_processors.debug",
                "django.core.context_processors.i18n",
                "django.core.context_processors.media",
                "django.core.context_processors.static",
                "django.core.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = 'wt.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'wt_db',
        'USER': 'postgres',
        'PASSWORD': 'PASSWORD',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}


AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True

db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)


ALLOWED_HOSTS = ['localhost', '127.0.0.1',]

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

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'wt/static'),
    os.path.join(BASE_DIR, 'wt/staticfiles'),
]

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

CKEDITOR_UPLOAD_PATH = 'uploads'
CKEDITOR_IMAGE_BACKEND = 'pillow'
CKEDITOR_BROWSE_SHOW_DIRS = True

Here my error log :

The joined path (E:\media\gallery\thumb\lost-thumb.jpg) is located outside of the base path component (E:\dev\wt\wt\wt\staticfiles)
[15/May/2016 20:01:41] "GET /page/gallery HTTP/1.1" 400 26

Thanks a lot for helping ! :)

EDIT :

principal structure

project folder


回答1:


Bro, you cant load staticfile when you use images on models, there is 2 different ways to work with images in django.

Statics files is for files that are static(images files like logo of your company, banners, javascript files, css files)

Media Files is for dinamic files like user photo, user gallery, product images

  1. Static Files - This way you use your staticfiles save at your static folder where you place it in static root at your settings.py and then you use {% load staticfiles %} and {% static '' %}
  2. Media Files - This files is that one you save with your models, ImageField, FileField and etc... that one you do not load as static, cuz they are not a static file (you can edit it from your models), that do not means you will save it on your database, this will generate a copy of your file with hashed name on it at you media folder where you place it in media root at your settings.py and media files you use like that {{ ..url }} so in your case gallery.thumbnail.url (btw, remind to call your gallery object at your views and send it to template to allow your to use it)

So the other anwers was right, you need to decide what you want to use, keep in mind that your path localy is different where you deploy, remember to use environment variables with the right path to set up in your settings

Django Docs: https://docs.djangoproject.com/en/1.11/topics/files/




回答2:


I gess it was a security issue. Even if "whitenoise" is good to serve true static files in production, it can't serve media files.

I was making a structure error :

# Don't place your 'media' files IN your 'static' file like this :

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

MEDIA_ROOT never have to be in the "static" file of your project (even if you can make it works in some ways, it's not a good practice I think).

'MEDIA' files (in production), have to be serve out of the Django project. I've read somewhere that we have to use a CDN. And firstly I choose CloudFlare (because it's free), but it wasn't working, cause you need a subdomain/hostname to point your MEDIA_ROOT, and CloudFlare doesn't give that. Finaly I choose Amazon S3.

So, in conclusion write something like {% static img.thumbnail.url %} make no sense. Because everything uploaded via admin/user haven't to be in "static".

Use {{ img.thumbnail.url }} instead.




回答3:


Try <img src="{{ img.thumbnail.image.url }}" alt="{{ img.alt}}">



来源:https://stackoverflow.com/questions/37241902/django-joined-path-is-located-outside-of-the-base-path-component-static-img

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!