仅生产环境出现Not Found错误的Django+React应用排查求助
Django+React部署到Render生产环境出现404问题排查
问题描述
Django后端+React前端应用在开发环境运行正常,但部署到Render平台生产环境时,出现「Not Found: The requested resource was not found on this server」错误,怀疑问题出在settings.py配置中,附上App.jsx路由代码,已排查两天未定位问题。
错误截图


相关代码
settings.py
from pathlib import Path import os import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get('SECRET_KEY', default='your secret key') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = 'RENDER' not in os.environ ALLOWED_HOSTS = [] RENDER_EXTERNAL_HOSTNAME = os.environ.get('RENDER_EXTERNAL_HOSTNAME') if RENDER_EXTERNAL_HOSTNAME: ALLOWED_HOSTS.append(RENDER_EXTERNAL_HOSTNAME) # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'corsheaders', 'rest_framework', 'coreapi', 'tareas', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'calendar_app.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], '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', ], }, }, ] WSGI_APPLICATION = 'calendar_app.wsgi.application' # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases DATABASES = { 'default': dj_database_url.config( default='postgresql://postgres:postgres@localhost/postgres', conn_max_age=600) } # Password validation # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators 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', }, ] # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.2/howto/static-files/ STATIC_URL = 'static/' if not DEBUG: # Tell Django to copy statics to the `staticfiles` directory # in your application directory on Render. STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # Turn on WhiteNoise storage backend that takes care of compressing static files # and creating unique names for each version so they can safely be cached forever. STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # cors auth CORS_ALLOWED_ORIGINS = ['http://localhost:5173'] REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', }
App.jsx
import "./App.css"; import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; import { TaskPage } from "./pages/TaskPage"; import { TaskFormPage } from "./pages/TaskFormPage"; import { Navigation } from "./components/Navigations"; import { TaskEditPage } from "./pages/TaskEditPage"; function App() { return ( <BrowserRouter> <Navigation></Navigation> <Routes> <Route path="/" element={<Navigate to="/tasks" />} /> <Route path="/tasks" element={<TaskPage />} /> <Route path="/tasks-create" element={<TaskFormPage />} /> <Route path="/tasks-edit" element={<TaskEditPage />} /> </Routes> </BrowserRouter> ); } export default App;
解决方案
1. 修复React路由与Django路由的冲突
生产环境中用户直接访问/tasks这类React路由时,Django会优先处理请求,但Django路由中没有对应配置,导致404。需在Django主URL配置中添加兜底路由,将非API请求转发到React入口页:
修改calendar_app/urls.py:
from django.contrib import admin from django.urls import path, include from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('tareas.urls')), # 替换为你的实际API路由前缀 # 兜底路由,所有非API请求返回React入口页 path('', TemplateView.as_view(template_name='index.html')), ]
同时需将React构建产物配置到Django中:
- 在React项目执行
npm run build,将build目录下的index.html复制到Django的templates目录,build/static下的文件复制到Django的static目录;或者在settings.py中添加静态文件目录:
STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'frontend/build/static'), # 替换为你的React build/static路径 ]
2. 更新CORS配置
当前CORS_ALLOWED_ORIGINS仅允许本地开发地址,生产环境需添加Render部署的前端域名:
# settings.py CORS_ALLOWED_ORIGINS = [ 'http://localhost:5173', 'https://your-render-frontend-domain.onrender.com', # 替换为你的实际前端域名 ]
3. 验证ALLOWED_HOSTS配置
确保ALLOWED_HOSTS包含Render的后端域名,可直接指定或保留原有逻辑:
ALLOWED_HOSTS = ['your-render-backend-domain.onrender.com']
4. 确保静态文件正确收集
在Render的构建命令中添加静态文件收集步骤,示例Build Command:
npm run build --prefix frontend && python manage.py collectstatic --noinput
5. 检查DEBUG模式
当前DEBUG = 'RENDER' not in os.environ在生产环境会自动关闭,符合安全要求,如需临时排查可临时开启,但生产环境务必保持关闭。
内容的提问来源于stack exchange,提问作者MrJonesBones
相关产品推荐
相关产品推荐

