1. 用户点击“Apply Now”按钮(前端操作)
- 动作:用户点击页面上的“Apply Now”按钮。
- 前端代码做了什么:
- 阻止按钮默认跳转(因为不想直接打开链接,而是先记录状态)。
- 用
window.open(link, '_blank')
在新标签页打开职位申请链接(比如企业官网的申请页面)。 - 把当前职位的信息(
jobId
、jobTitle
等)存到 sessionStorage
(相当于“临时备忘录”,记录“用户刚刚点了哪个职位”)。
- 路由相关:这一步还没涉及后端路由,只是前端在浏览器内操作。
2. 用户返回职位匹配页面(前端触发模态框)
- 动作:用户在新标签页填完申请后,切换回原来的职位匹配页面(标签页重新获得焦点)。
- 前端代码做了什么:
- 浏览器检测到页面重新获得焦点(
window.focus
事件),检查 sessionStorage
中是否有“临时备忘录”(即是否点击过“Apply Now”但未确认)。 - 如果有,弹出模态框问用户:“你确认已经申请了这个职位吗?”
- 路由相关:这一步还是前端在浏览器内操作,未访问后端。
3. 用户点击“是的,我已申请”(前端发送请求到后端)
- 前端代码做了什么:
- 从
sessionStorage
中取出 jobId
(职位ID)。 - 构造一个 **POST 请求**,发送到后端URL:
/job/${jobId}/update_status/
(注意!这里的URL路径必须和后端路由匹配)。 - 请求中包含:
- 要更新的状态(如“applied”)。
- CSRF令牌(从cookie中获取,用于防止跨站攻击)。
- 路由如何匹配?
- 根路由配置:
path("", include("matcher.urls"))
→ 所有URL直接从根路径(/
)开始匹配。 - matcher应用的路由:
path('job/<str:job_id>/update_status/', ...)
→ 匹配以 job/
开头、包含 job_id
参数的URL。 - 最终匹配的URL:比如
http://your-site.com/job/123/update_status/
(正确)。 - 之前的错误:前端写成了
http://your-site.com/matcher/job/123/update_status/
,但根路由没有 /matcher/
前缀,导致找不到路由(404错误)。
4. 后端处理请求(更新状态)
- 后端收到请求后做什么:
- 从URL中提取
job_id
(比如“123”),找到对应的职位信息。 - 从请求中验证CSRF令牌(确保请求是合法用户发送的,不是黑客伪造的)。
- 更新该职位对应用户的状态(比如从“未申请”改为“已申请”),保存到数据库。
- 返回一个JSON响应给前端(如
{"status": "success"}
)。
- 路由的作用:后端通过路由规则,将URL
job/<job_id>/update_status/
映射到 update_job_application_status
视图函数,确保请求被正确处理。
5. 前端处理响应(更新页面显示)
- 前端收到响应后做什么:
- 如果响应成功,更新页面上该职位的状态(比如显示“已申请”)。
- 清除
sessionStorage
中的临时记录(避免下次切换标签页时重复弹出模态框)。
为什么路由会让你蒙?一张图秒懂!
用户操作 → 前端行为 → 目标URL → 路由匹配逻辑
──────────────────────────────────────────────────────
点击“Apply Now” → 打开新标签页 + 存临时记录 → 无(未访问后端)
返回页面 → 弹出模态框 → 无(未访问后端)
点击“确认” → 发送请求到 /job/123/update_status/ →
根路由("")+ matcher应用路由(job/...)→ 匹配成功!
总结:核心逻辑+避坑点
- 前端URL路径必须和后端路由完全一致:
- 根路由给应用的前缀是啥,前端URL就以啥开头。
- 例子中根路由是
path("", include(...))
,所以前端URL直接以 /job/...
开头,不加多余前缀。
- 模态框的触发时机:
- 不是点击“Apply Now”立刻弹出,而是等用户返回页面(标签页聚焦)时,根据
sessionStorage
判断是否需要弹出。
- CSRF令牌的作用:
- 就像你去银行办业务需要带身份证,前端请求后端时必须带CSRF令牌,否则会被拒绝(返回错误页面,导致JSON解析失败)。