React-Django项目:传递Token并按用户地区过滤学校数据
解决方案:按Token中地区ID过滤学校列表
需求说明
当前项目中Schools.js会展示所有学校,需要调整为仅展示满足以下条件的学校:
dist_office_id等于用户Token中的place_id字段值school_name不为空
同时需要将前端Token传递到后端,动态提取place_id,替换当前硬编码的place_id=3逻辑,适配不同地区办公人员的权限。
前端代码修改
1. 更新SchoolService.js,携带Token请求头
修改getSchools函数,添加Authorization请求头,把前端的JWT Token传给后端:
import axios from 'axios'; export function getSchools(token) { // 配置请求头,携带JWT Token const config = { headers: { 'Authorization': `Bearer ${JSON.parse(token)}` } }; return axios.get("http://127.0.0.1:8000/api/schools/", config) .then(response => response.data) }
2. 更新Schools.js,传递Token并处理请求
修改useEffect中的调用逻辑,把本地存储的Token传给getSchools,同时优化Token判断逻辑:
import { useEffect, useState } from 'react'; import jwt_decode from "jwt-decode"; import {Table, Button, ButtonToolbar} from 'react-bootstrap'; import {FaEdit} from 'react-icons/fa'; import {RiDeleteBin5Line} from 'react-icons/ri'; import {getSchools, deleteSchool} from '../services/SchoolService'; import AddSchoolModal from '../components/modals/api_modals/AddSchoolModal'; import UpdateSchoolModal from '../components/modals/api_modals/UpdateSchoolModal'; const Schools = () => { const [schools, setSchools] = useState([]); const [addModalShow, setAddModalShow] = useState(false); const [editModalShow, setEditModalShow] = useState(false); const [editSchool, setEditSchool] = useState([]); const [isUpdated, setIsUpdated] = useState(false); // 获取本地存储的Token const token = localStorage.getItem("authTokens"); useEffect(() => { let mounted = true; if(schools.length && !isUpdated) { return; } // 仅当存在Token时发起请求 if(token) { getSchools(token) .then(data => { if (mounted) { setSchools(data); } }) .catch(err => { console.error("获取学校列表失败:", err); }) } return () => { mounted = false; setIsUpdated(false); } }, [isUpdated, schools, token]); // 以下原有逻辑保持不变 const handleAdd = (e) => { e.preventDefault(); setAddModalShow(true); }; const handleUpdate = (e, school) => { e.preventDefault(); setEditModalShow(true); setEditSchool(school); }; const handleDelete = (e, id) => { if(window.confirm('Are you sure?')) { e.preventDefault(); deleteSchool(id) .then((result) => { alert(result); setIsUpdated(true); }, (error) => { alert("Failed to Delete!"); }) } }; let AddModalClose = () => setAddModalShow(false); let EditModalClose = () => setEditModalShow(false); return ( <div className="row side-row"> <Table striped bordered hover size="sm"> <thead> <tr> <th>S/N</th> <th>School</th> <th>Action</th> </tr> </thead> <tbody> {schools.map((school, index) => <tr key={school.id}> <td>{index + 1}</td> <td>{school.school_name}</td> <td> <Button className='mr-2' variant="danger" size="sm" onClick={event => handleDelete(event,school.id)}> <RiDeleteBin5Line /> </Button> <span> </span> <Button className='mr-2' variant="primary" size="sm" onClick={event => handleUpdate(event,school)}> <FaEdit /> </Button> <UpdateSchoolModal show={editModalShow} onHide={EditModalClose} school={editSchool} setUpdated={setIsUpdated}> </UpdateSchoolModal> </td> </tr>)} </tbody> </Table> <ButtonToolbar> <Button variant="success" onClick={handleAdd}>Add School</Button>{' '} <AddSchoolModal show={addModalShow} onHide={AddModalClose} setUpdated={setIsUpdated}> </AddSchoolModal> </ButtonToolbar> </div> ); }; export default Schools;
后端代码修改(views.py)
修改SchoolView的get方法,从请求头的Token中解析出place_id,替换硬编码逻辑:
import jwt from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.exceptions import AuthenticationFailed, Http404 from .models import Place from .serializers import PlaceSerializer class SchoolView(APIView): def get_school(self, pk): try: school = Place.objects.get(id=pk) return school except Place.DoesNotExist: raise Http404 def get(self, request, pk=None): if pk: data = self.get_school(pk) serializer = PlaceSerializer(data) else: # 从Authorization头中提取Token auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): raise AuthenticationFailed('Invalid or missing token') token = auth_header.split(' ')[1] try: # 解析Token,替换为项目实际使用的JWT密钥 decoded_token = jwt.decode(token, 'your_jwt_secret_key', algorithms=['HS256']) place_id = decoded_token.get('place_id') except jwt.ExpiredSignatureError: raise AuthenticationFailed('Token expired') except jwt.InvalidTokenError: raise AuthenticationFailed('Invalid token') # 按条件过滤学校:dist_office_id匹配且school_name不为空 if place_id is not None: data = Place.objects.filter(dist_office_id=place_id, school_name__isnull=False) serializer = PlaceSerializer(data, many=True) else: # 无place_id时返回空列表 data = Place.objects.none() serializer = PlaceSerializer(data, many=True) return Response(serializer.data)
注意事项
- 替换代码中的
your_jwt_secret_key为项目实际使用的JWT密钥 - 确保Django项目已安装
pyjwt库,可通过pip install pyjwt安装 - 前端存储的
authTokens是JSON字符串,请求时需用JSON.parse(token)解析为原始Token
内容的提问来源于stack exchange,提问作者Hamid Baisaana
相关产品推荐
相关产品推荐

