如何用Fetch实现Django多对多关系中对象的移除(取消关注)
Django取消关注功能的实现方案
1. HTTP方法选择:用DELETE
选DELETE是因为你要删除的是「登录用户和目标用户之间的关注关联关系」,而非更新用户资源本身。PUT语义上是用来替换整个资源(比如覆盖用户的所有粉丝列表),完全不符合你只移除单个粉丝的需求。
2. 后端视图实现(Django)
URL配置
在urls.py里添加路由,把目标用户ID放在URL路径中:
from django.urls import path from .views import UnfollowUserView urlpatterns = [ # 其他路由... path('users/<int:target_id>/unfollow/', UnfollowUserView.as_view(), name='unfollow-user'), ]
视图逻辑
用类视图处理DELETE请求,核心是移除关联关系:
from django.http import JsonResponse from django.views import View from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import get_object_or_404 from .models import User class UnfollowUserView(LoginRequiredMixin, View): def delete(self, request, target_id): target_user = get_object_or_404(User, id=target_id) # 移除登录用户与目标用户的关注关联 target_user.followers.remove(request.user) return JsonResponse({'status': 'success', 'message': '已取消关注'}, status=200)
3. 前端Fetch请求写法
不需要在请求体里传followers字段,目标用户ID通过URL传递,登录用户信息由后端认证(Session/Token)获取:
// 假设post.user.id是目标用户的ID const targetUserId = post.user.id; // 辅助函数:获取Django的CSRF令牌(从cookie中读取) function getCsrfToken() { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, 10) === 'csrftoken=') { cookieValue = decodeURIComponent(cookie.substring(10)); break; } } } return cookieValue; } // 发送取消关注请求 fetch(`/users/${targetUserId}/unfollow/`, { method: 'DELETE', credentials: 'include', // 带Session cookie,确保后端能识别登录用户 headers: { 'X-CSRFToken': getCsrfToken(), // Django要求的CSRF令牌 'Accept': 'application/json' } }) .then(response => { if (response.ok) { // 成功后更新UI,比如把按钮文字改成"关注" console.log('取消关注成功'); } else { return response.json().then(data => { console.error('取消关注失败:', data.message || '未知错误'); }); } }) .catch(error => console.error('请求出错:', error));
额外注意事项
- 可以在后端视图中增加判断:如果登录用户本来就没关注目标用户,返回
400 Bad Request状态码,避免无效操作 - 如果用Token认证(比如JWT),把
credentials: 'include'换成在headers里加Authorization: Bearer ${token}
内容的提问来源于stack exchange,提问作者Maya Twik
相关产品推荐
相关产品推荐

