【问题标题】:All static assets coming back as "404 (Not found)" in Django/React app在 Django/React 应用程序中以“404(未找到)”的形式返回的所有静态资产
【发布时间】:2018-12-07 20:12:50
【问题描述】:

我的应用程序位于服务器路径/home/myapp/

当执行python manage.py collectstatic 时,静态资产位于/home/myapp/src/static/

它从/home/myapp/src/assets/复制资产。

我已经尝试过DEBUG TrueFalse

当我导航到位于 https://test.example.com 的 Web 应用程序时,它告诉我位于 /home/mpapp/src/assets/ 的所有资产都是 404 (Not Found),尽管文件在那里。

另外,我的 Web 服务器设置是 Apache,带有 Gunicorn 的反向代理。我正在使用gunicorn wsgi 为应用程序提供服务,该应用程序在127.0.0.1:8000 为应用程序提供服务,这是Apache 所在的ProxyPass。我已经针对一个全新的 Django 应用程序进行了测试,并且此设置可以正常使用,因此不应该是 Apache 和 Gunicorn 的配置方式。

我一直在做的是:

1) npm start 编译 React 前端资产

2) python manage.py collectstatic 将资产移动到 /static/

3) 在manage.pywsgi.py 所在的位置运行gunicorn wsgi

一些代码会有所帮助。这是我的settings.py

import os
import sys
import json
import datetime

from unipath import Path
from django.core.exceptions import ImproperlyConfigured

# Import JSON file 
print(Path(__file__))
with open('./config/config.json') as f:
    s = json.loads(f.read())

def get_settings(settings, s=s):
    try:
        return s[settings]
    except KeyError:
        error_msg = 'Set the {0} environment vaiable'.format(settings)
        raise ImproperlyConfigured(error_msg)


# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = Path(__file__).ancestor(2)


# Quick-start development settings - unsuitable for production

# SECURITY WARNING: keep the secret key used in production secret! 
SECRET_KEY = get_settings('SECRET_KEY')


ALLOWED_HOSTS = [
    '*',
]

# Application definition

INSTALLED_APPS = [
    # Base packages
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Third party packages
    'rest_framework',
    'rest_framework_jwt',
    'webpack_loader',
    'tinymce',

    # Local packages
    'authentication',
    'documents',
    'contact',
    'home',
    'results',
    'users'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

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


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

WSGI_APPLICATION = 'wsgi.application'


# Password validation
AUTH_USER_MODEL = 'authentication.User'

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',
    },
]


# REST Framework settings
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}


# DRF JWT token settings
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    'JWT_ALLOW_REFRESH': True,
}


# Webpack settings
WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'bundles/',
        'STATS_FILE': os.path.join(BASE_DIR, './config/webpack-stats.json'),
    }
}


STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'assets'),
)

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

# Static files (CSS, JavaScript, Images)

STATIC_URL = '/static/'


# Internationalization

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'America/Los_Angeles'

USE_I18N = True

USE_L10N = True

USE_TZ = False


# EMAIL SETTINGS

EMAIL_HOST = get_settings('EMAIL_HOST')

EMAIL_HOST_USER = get_settings('EMAIL_HOST_USER')

EMAIL_HOST_PASSWORD = get_settings('EMAIL_HOST_PASSWORD')

EMAIL_PORT = get_settings('EMAIL_PORT')

EMAIL_USE_TLS = True

我的目录结构如下所示,基于两个 Scoops:

testapp
    assets
        bundles
            css
                app.e1c352f1.css
            js
                vendor.s63d4f.js
                manifrest.5fd4g.js
                app.dsr5h4.js
        css
            bootstrap.css
        img
        scss
    config
         config.json
         settings.py
         urls.py
         webpack.config.js
    react
         index.jsx
    static
         admin
         bundles
             css
                app.e1c352f1.css
             js
                vendor.s63d4f.js
                manifrest.5fd4g.js
                app.dsr5h4.js
         css
             bootstrap.css
         img
         rest_framework
         scss
    templates
         index.html
    manage.py
    wsgi.py

另外,我的urls.py,如果这可能相关的话:

from django.conf.urls import url, include
from django.contrib import admin
from django.views.generic.base import TemplateView

from home.views import GetHomeAPIView

    urlpatterns = [
        # Admin URL
        url(r'^admin', admin.site.urls),

        # API authentication entry point   
        url(r'^api/auth/', include('authentication.urls', namespace='signin')),

        # API /home entry point   
        url(r'^api/home/', GetHomeAPIView.as_view(), name='home'),

        # API /contact entry point   
        url(r'^api/contact/', include('contact.urls', namespace='contact')),

        # API /contact entry point   
        url(r'^api/users/', include('users.urls', namespace='users')),

        # Any requets that come through serve the index.html
        url(r'^$', TemplateView.as_view(template_name='index.html')),
    ]

所以不确定 100% 该怎么做。

我尝试将STATIC_ROOTSTATIC_URL 都更改为实际路径/home/myapp/src/static/,但没有做任何事情。

对于如何解决这个问题有点困惑,我查看的 SO 问题并没有解决这个问题。

【问题讨论】:

标签: django reactjs apache gunicorn


【解决方案1】:

好吧,我通过在urls.py 中执行以下操作来开始加载:

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

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

也可以在这里阅读。

https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-during-development

它正在工作,但话虽如此,这些部分被称为“在开发期间提供静态文件”......我正在为生产做这个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-23
    • 2013-02-12
    • 2018-06-16
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多