Django Rest Framework仅单个URL出现CSRF cookie未设置错误的原因
看起来这个CSRF错误的根源其实和你的视图代码里的一个小问题有关,其他表单正常是因为它们的视图没有触发这个隐藏的错误。让我一步步拆解:
核心问题:视图依赖不存在的URL参数
你的RateOpportunity视图重写了get_queryset方法,试图从self.kwargs["pk"]获取ID,但你的URL配置path("opportunities/rate/", RateOpportunity.as_view)根本没有捕获pk参数!
当Django处理这个POST请求时,视图流程中会调用get_queryset(哪怕CreateAPIView本身不需要查询集来创建对象),这时候会直接抛出KeyError异常。这个异常会干扰正常的响应流程,导致CSRF cookie没有被正确设置或返回给前端,最终触发"CSRF cookie未设置"的错误——虽然表面上看是CSRF的问题,实际上是后端视图的参数错误导致的连锁反应。
修复步骤
1. 移除多余的get_queryset方法
CreateAPIView用于创建新对象,完全不需要重写get_queryset(这个方法主要用于查询类视图,比如ListAPIView或RetrieveAPIView)。把这段代码删掉:
def get_queryset(self): id = self.kwargs["pk"] return Opportunity.objects.all().filter(opportunity=id)
2. 按需调整URL或业务逻辑
如果你确实需要在创建评分时关联某个特定的Opportunity,有两种方式:
- 方式一:从请求体获取Opportunity ID
在序列化器中接收opportunity_id字段,然后在perform_create中关联对象:class RateOpportunity(generics.CreateAPIView): permission_classes = [permissions.IsAuthenticated] serializer_class = OpportunityRateSerializer name = "rate-opportunity" def perform_create(self, serializer): # 从请求数据中获取opportunity_id,确保序列化器已定义该字段 opportunity_id = self.request.data.get("opportunity_id") opportunity = Opportunity.objects.get(pk=opportunity_id) serializer.save(user=self.request.user, opportunity=opportunity) - 方式二:修改URL添加pk参数
如果希望从URL路径传递Opportunity ID,修改URL配置:
然后在path("opportunities/rate/<int:pk>/", RateOpportunity.as_view()),perform_create中获取pk:def perform_create(self, serializer): opportunity = Opportunity.objects.get(pk=self.kwargs["pk"]) serializer.save(user=self.request.user, opportunity=opportunity)
3. 验证CSRF token的携带(可选)
虽然你说其他表单正常,但可以确认Vue请求是否正确携带了CSRF token:确保请求头包含X-CSRFToken,值从Django设置的csrftoken cookie中获取。比如在Vue中可以这样获取:
const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken=')).split('=')[1]; // 然后在POST请求的headers中设置: headers: { 'X-CSRFToken': csrfToken }
完成以上修改后,这个端点的CSRF错误应该就会消失了——因为后端不再抛出异常,响应流程恢复正常,CSRF cookie也能正确设置和验证。
内容的提问来源于stack exchange,提问作者crawlingdev

