Django+React+Postgres一对多关联hero_id无法绑定当前登录用户id问题
问题根源
你遇到的现象是因为三个核心问题导致的:
- 后端接口未配置登录认证,无法识别当前发起请求的是哪个用户
- 序列化器保存英雄数据时,没有主动将当前登录用户赋值给
hero关联字段,ORM自动使用了模型定义的默认值1 - 前端发起请求时未携带登录凭证,后端无法获取用户身份
修复步骤
1. 调整序列化器
修改serializer.py中的UsersHeroesSerializer,补充hero字段并设为只读,移除无效的parent定义:
class UsersHeroesSerializer(serializers.ModelSerializer): hero = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = UsersHeroes fields = ['id', 'name', 'race_type', 'class_type', 'STR', 'DEX', 'CON', 'INT', 'WIS', 'CHA', 'hero']
2. 调整视图逻辑
修改views.py,给接口增加登录校验,保存数据时传入当前登录用户:
from rest_framework.permissions import IsAuthenticated from rest_framework.authentication import TokenAuthentication # 若使用JWT认证,替换为对应的JWT认证类 class ReactView(APIView): serializer_class = UsersHeroesSerializer # 配置认证规则:必须登录才能访问接口 authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def get(self, request): # 若需要只返回当前用户的英雄,可改为 UsersHeroes.objects.filter(hero=request.user) heroes = UsersHeroes.objects.all() serializer = UsersHeroesSerializer(heroes, many=True) return Response(serializer.data) def post(self, request): serializer = UsersHeroesSerializer(data=request.data) if serializer.is_valid(raise_exception=True): # 保存时主动将当前用户赋值给hero关联字段 serializer.save(hero=request.user) return Response(serializer.data)
注:原代码中的csrf_exempt装饰器可以删除,使用Token/JWT认证时不需要CSRF校验。
3. 调整前端请求代码
用户登录成功后要将返回的认证token存在本地(比如localStorage),发起创建英雄请求时在请求头携带token:
const onSubmit = (e) => { e.preventDefault(); // 取本地存储的登录token,key名要和你登录时存的一致 const authToken = localStorage.getItem('user_token'); const postData = { name, race_type: selectedRace, class_type: selectedClass, STR: valueStr, DEX: valueDex, CON: valueCon, INT: valueInt, WIS: valueWis, CHA: valueCha, }; Axios.post(`${process.env.REACT_APP_API_URL}/heroes/`, postData, { headers: { 'Authorization': `Token ${authToken}` // 若使用JWT认证,改为 `Bearer ${authToken}` } }) .then((res) => { console.log(res); }) .catch((err) => { console.error(err); }); }
可选优化
可以删除UsersHeroes模型中hero字段的默认值配置,避免后续出现非预期的默认赋值:
# 修改前 # hero = models.ForeignKey(UserAccount, default = 1, on_delete=models.CASCADE) # 修改后 hero = models.ForeignKey(UserAccount, on_delete=models.CASCADE)
修改后执行python manage.py makemigrations和python manage.py migrate同步数据库即可。
内容的提问来源于stack exchange,提问作者gwuppy
相关产品推荐
相关产品推荐

