Django与Angular整合:项目结构与路由配置加载模板并获取API数据
我明白你卡在哪了——把Django作为API后端,同时让Angular负责前端渲染,既要分开两者的模板系统,又要让它们在同一个域名下配合工作,确实容易绕晕。下面给你一个可直接运行的完整方案,包含文件夹结构、Django配置、Angular配置,完全避开混合模板的问题。
一、核心思路
先理清楚分工:
- Django只做两件事:提供REST API接口,以及返回Angular的入口HTML文件(你的
angtemplate.html)。 - 所有前端渲染、路由、数据展示逻辑都交给Angular,完全不需要在Django模板里写Angular语法,两者彻底分离,各司其职。
二、可运行的文件夹结构示例
your_django_project/ ├── your_django_project/ # Django项目配置目录 │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── apitest/ # 你的Django应用 │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── views.py │ ├── urls.py # 应用级URL路由 │ ├── templates/ │ │ └── apitest/ │ │ └── angtemplate.html # Angular入口模板(仅加载静态资源) │ └── static/ │ └── apitest/ │ └── angular_app/ # Angular构建后的产物(复制dist文件夹内容到这里) │ ├── favicon.ico │ ├── main.[hash].js │ ├── polyfills.[hash].js │ ├── runtime.[hash].js │ └── styles.[hash].css └── manage.py
说明:Angular开发完成后,执行构建命令把产物复制到Django的静态资源目录,Django的入口模板只负责引入这些资源,不做任何渲染逻辑。
三、Django端配置步骤
1. 编写入口视图(apitest/views.py)
写一个极简视图,只返回Angular的入口模板:
from django.shortcuts import render def angular_entry(request): # 不需要传递数据,数据由Angular自己从API拉取 return render(request, 'apitest/angtemplate.html')
2. 配置应用级URL(apitest/urls.py)
把/apifetch路径指向上面的视图,同时保留你的API路由:
from django.urls import path from . import views urlpatterns = [ # 你的API路由(已注册的JSON接口) path('api/data/', views.your_api_view, name='api-data'), # Angular入口页面路由 path('apifetch/', views.angular_entry, name='angular-entry'), ]
3. 配置项目级URL(your_django_project/urls.py)
把apitest应用的路由挂载到根路径:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('apitest.urls')), ]
4. 确认静态文件配置(settings.py)
确保这些配置已经存在:
INSTALLED_APPS = [ # ... 'django.contrib.staticfiles', 'apitest', # 注册你的应用 # ... ] STATIC_URL = '/static/' # 生产环境执行collectstatic时的静态文件根目录(开发阶段可忽略) STATIC_ROOT = BASE_DIR / 'staticfiles'
四、Angular端配置步骤
1. 基础Angular项目结构(开发时)
假设你创建了名为angular-apifetch的Angular项目,核心结构如下:
angular-apifetch/ ├── src/ │ ├── app/ │ │ ├── app.component.ts │ │ ├── app.component.html │ │ ├── app.module.ts │ │ ├── data.service.ts # 调用Django API的服务 │ │ └── app-routing.module.ts # Angular路由(可选) │ ├── index.html │ └── styles.css └── angular.json
2. 编写API数据服务(data.service.ts)
用来从Django API拉取数据:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { // 替换成你的Django API实际路径 private apiUrl = 'http://127.0.0.1:8000/api/data/'; constructor(private http: HttpClient) { } getData(): Observable<any> { return this.http.get(this.apiUrl); } }
3. 编写根组件逻辑(app.component.ts)
调用服务获取数据并存储:
import { Component, OnInit } from '@angular/core'; import { DataService } from './data.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { apiData: any[] = []; errorMsg: string = ''; constructor(private dataService: DataService) { } ngOnInit(): void { this.dataService.getData().subscribe( (response) => { this.apiData = response; }, (error) => { this.errorMsg = '加载数据失败:' + error.message; } ); } }
4. 编写组件模板(app.component.html)
展示从API获取的数据:
<h1>Django API 数据展示</h1> <div *ngIf="apiData.length; else loading"> <ul> <li *ngFor="let item of apiData"> {{ item.title }} - {{ item.content }} </li> </ul> </div> <ng-template #loading> <p>正在加载数据...</p> </ng-template> <div *ngIf="errorMsg" class="error"> {{ errorMsg }} </div>
5. 构建Angular项目
在Angular项目根目录执行构建命令:
# 生产环境构建(带哈希值,防止缓存) ng build --prod # 开发阶段可关闭哈希,方便调试:ng build --output-hashing=none
构建完成后,把dist/angular-apifetch/里的所有文件复制到Django的apitest/static/apitest/angular_app/目录下。
五、编写Django入口模板(angtemplate.html)
这个模板完全不用Django渲染逻辑,只负责加载Angular的静态资源和挂载根组件:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Angular + Django API</title> {% load static %} <!-- 引入Angular样式文件 --> <link rel="stylesheet" href="{% static 'apitest/angular_app/styles.[hash].css' %}"> </head> <body> <!-- Angular根组件的挂载点 --> <app-root></app-root> <!-- 按顺序引入Angular的JS文件(替换[hash]为实际构建后的哈希值) --> <script src="{% static 'apitest/angular_app/runtime.[hash].js' %}"></script> <script src="{% static 'apitest/angular_app/polyfills.[hash].js' %}"></script> <script src="{% static 'apitest/angular_app/main.[hash].js' %}"></script> </body> </html>
提示:如果开发阶段关闭了哈希,直接用styles.css、runtime.js等文件名即可,不用替换哈希。
六、测试运行
- 启动Django开发服务器:
python manage.py runserver
- 访问
http://127.0.0.1:8000/apifetch/,就能看到Angular页面加载并从Django API拉取数据展示了。
关于混合模板的疑惑解答
你听到的“不应混合Django与Angular模板”是完全正确的:
- Django模板是服务器端渲染,Angular是客户端渲染,两者的
{{ }}语法会直接冲突,导致渲染混乱。 - 我们的方案彻底分离了两者:Django只提供一个空白的“壳”页面,所有前端逻辑都由Angular在浏览器中完成,数据通过API异步获取,职责清晰,维护起来也更简单。
如果开发阶段想实时调试Angular,不用每次都构建复制,可以启动Angular开发服务器并配置代理:
- 在Angular项目根目录创建
src/proxy.conf.json:
{ "/api/*": { "target": "http://127.0.0.1:8000", "secure": false } }
- 启动Angular时指定代理:
ng serve --proxy-config src/proxy.conf.json
这样Angular可以直接调用/api/data/而不用写全路径,同时Django负责API,Angular负责前端,开发效率更高。
内容的提问来源于stack exchange,提问作者Marcus Grass

