Django集成Angular:将未匹配URL重写至index.html
这问题我碰到过好多次,本质就是单页应用(SPA)的前端路由和后端服务器路由的冲突:当你在Angular应用内点击链接时,路由是Angular在前端直接处理的,不会给Django发请求;但你直接在地址栏输入URL或者刷新页面时,浏览器会直接向Django服务器请求这个路径,而Django的URL配置里根本没有对应的路由,自然就返回404了。
下面是具体的解决步骤,一步步来:
1. 正确构建Angular应用
首先把你的Angular应用构建成生产环境的静态文件:
ng build --prod
(现在Angular 16+默认ng build就是生产模式,也可以直接用这个命令)
执行完后会生成一个dist/[你的项目名]文件夹,里面包含index.html和所有静态资源(js、css、assets等)。
2. 把Angular的文件放到Django对应的目录里
- 将
dist里的index.html移动到Django项目的templates目录下,比如新建templates/angular/文件夹,把index.html放进去。 - 将
dist里的其他静态文件(包括js、css、assets文件夹)移动到Django的static/angular/目录下。
注意:如果你的Django项目里
TEMPLATES配置的DIRS没有包含templates目录,记得在settings.py里加上:TEMPLATES = [ { ... 'DIRS': [BASE_DIR / 'templates'], ... }, ]
3. 配置Django的URLconf,添加兜底路由
在你的主urls.py里,添加一个最后执行的路由规则,把所有非API、非静态资源的请求都转发到Angular的index.html,让Angular的前端路由来处理:
from django.urls import path, re_path from django.views.generic import TemplateView # 导入你的其他路由,比如admin、API路由等 from django.contrib import admin from django.urls import include urlpatterns = [ # 先放你的Django原生路由,比如admin、API接口 path('admin/', admin.site.urls), path('api/', include('your_api_app.urls')), # 最后放这个兜底路由,匹配所有其他路径 re_path(r'^.*$', TemplateView.as_view(template_name='angular/index.html')), ]
这里的关键是兜底路由一定要放在所有路由的最后,否则会把你的API请求、admin请求也拦截掉,导致这些功能无法使用。
4. 确保Angular静态资源的路径正确
打开你放到templates/angular/里的index.html,把里面的静态资源引用路径改成Django的静态资源格式,比如原来的:
<script src="main.xxxx.js"></script>
改成用Django的static模板标签:
<script src="{% static 'angular/main.xxxx.js' %}"></script>
或者更省事的方式是在构建Angular的时候指定base-href,这样生成的index.html里的路径会自动加上前缀:
ng build --prod --base-href /static/angular/
这样构建出来的静态资源路径就会自动变成/static/angular/main.xxxx.js,不用手动修改index.html了。
5. 测试验证
- 开发环境:启动Django服务器,直接在地址栏输入
niftysite.com/team(本地的话就是localhost:8000/team),应该能正常加载页面了。 - 生产环境:记得执行
python manage.py collectstatic把所有静态资源收集到STATIC_ROOT指定的目录,然后用Nginx等服务器代理静态资源和Django请求。
这样配置之后,不管是应用内导航还是直接输入URL,都能正常访问Angular的页面了~
内容的提问来源于stack exchange,提问作者user9487981

