Django模板登录后跳转React页面并传递认证信息的实现方案咨询
我来一步步帮你搞定这个需求,基于你用的是Django Session Authentication Middleware,下面是具体的实现方案:
1. 先让Django把前端路由交给React处理
首先得配置Django的路由,让所有非API的请求都转发到React的入口页面(index.html),这样React的路由才能正常工作。
在你的Django主urls.py里添加一个catch-all路由:
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('your_api_app.urls')), # 保留你的API路由 # 所有非API请求都指向React的index.html path('', TemplateView.as_view(template_name='frontend/index.html')), ]
注意:把React构建后的index.html放到Django的templates/frontend/目录下,静态文件(js、css)放到Django的static/frontend/目录,或者用Whitenoise来托管React静态资源。
2. 修改Django登录逻辑,跳转至React页面
不管你用的是Django自带的登录视图还是自定义视图,登录成功后直接重定向到React的目标路由(比如/dashboard)即可。
自定义登录视图示例:
from django.contrib.auth import authenticate, login from django.shortcuts import redirect, render def custom_login(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # 跳转到React的首页路由 return redirect('/dashboard') else: return render(request, 'login.html', {'error': '账号或密码错误'}) return render(request, 'login.html')
用Django自带LoginView的配置:
from django.contrib.auth.views import LoginView path('login/', LoginView.as_view( template_name='login.html', success_url='/dashboard' # 登录成功后跳转到React路由 ), name='login'),
3. 把用户认证信息传递给React
这里有两种常用方案,你可以根据需求选:
方案一:Django渲染React入口时注入全局变量
直接在React的index.html模板里,用Django把用户信息渲染成全局JS变量,React初始化就能直接拿到:
<!-- templates/frontend/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React App</title> </head> <body> <div id="root"></div> <script> // 注入用户信息(已登录时才会有值) window.userInfo = {{ user|json_script:"user-data"|safe }}; </script> <!-- 引入React构建后的静态JS文件 --> <script src="{% static 'frontend/js/main.xxx.js' %}"></script> </body> </html>
然后在React的根组件里读取这个全局变量:
import React, { useEffect, useState } from 'react'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; function App() { const [currentUser, setCurrentUser] = useState(null); useEffect(() => { // 从全局变量获取用户信息 if (window.userInfo) { setCurrentUser(window.userInfo); } else { // 未登录则跳回Django登录页 window.location.href = '/login'; } }, []); if (!currentUser) { return <div>加载中...</div>; } return ( <Router> <div>欢迎回来,{currentUser.username}!</div> {/* 你的React路由和组件 */} <Routes> <Route path="/dashboard" element={<Dashboard user={currentUser} />} /> {/* 其他路由 */} </Routes> </Router> ); } export default App;
方案二:React通过API请求获取用户信息
如果不想用全局变量,也可以让React在初始化时调用Django的API获取用户信息,更符合RESTful规范:
首先在Django写一个获取当前用户的API视图:
from django.contrib.auth.decorators import login_required from django.http import JsonResponse @login_required # 只有登录用户才能访问 def current_user(request): return JsonResponse({ 'id': request.user.id, 'username': request.user.username, 'email': request.user.email, # 你需要的其他用户字段 })
在API的urls.py里配置路由:
path('current-user/', views.current_user, name='current-user'),
然后React里用axios/fetch请求这个接口:
import React, { useEffect, useState } from 'react'; import axios from 'axios'; function App() { const [currentUser, setCurrentUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchUser = async () => { try { const res = await axios.get('/api/current-user/'); setCurrentUser(res.data); } catch (err) { // 请求失败说明未登录,跳回Django登录页 window.location.href = '/login'; } finally { setLoading(false); } }; fetchUser(); }, []); if (loading) return <div>加载中...</div>; return ( <div> <h1>Hello, {currentUser.username}!</h1> {/* 你的React组件 */} </div> ); } export default App;
因为用的是Session认证,浏览器会自动带上session cookie,Django的@login_required能正确识别用户身份。
4. 保护React路由(可选)
如果需要限制某些React路由只能登录用户访问,可以写一个路由守卫组件:
import { Navigate, Outlet } from 'react-router-dom'; function ProtectedRoute({ user }) { if (!user) { return <Navigate to="/login" replace />; } return <Outlet />; } export default ProtectedRoute;
然后在路由配置里使用:
<Routes> <Route path="/login" element={<Navigate to="/login" replace />} /> {/* 受保护的路由组 */} <Route element={<ProtectedRoute user={currentUser} />}> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/profile" element={<Profile />} /> </Route> <Route path="/" element={<Navigate to="/dashboard" replace />} /> </Routes>
5. 注销功能(可选)
可以在React里加一个注销按钮,调用Django的注销API:
# Django API视图 from django.contrib.auth import logout from django.http import JsonResponse def logout_user(request): logout(request) return JsonResponse({'success': True})
React里的注销逻辑:
const handleLogout = async () => { await axios.post('/api/logout/'); window.location.href = '/login'; };
内容的提问来源于stack exchange,提问作者nael

