API数据获取故障求助:从Forbidden错误转为AttributeError——'networthChart'对象无'COOKIES'属性
首先,咱们来拆解你遇到的两个问题:一开始的Forbidden错误,以及后来出现的AttributeError: 'networthChart' object has no attribute 'COOKIES'。
1. 先解决AttributeError的核心问题
这个错误的根源很明确:你在视图代码里错误地尝试从视图类实例(也就是self)获取COOKIES属性,但COOKIES是**request对象的专属属性**,视图类本身并没有这个属性。
如果你在代码里写了类似这样的行:
cookie_token = self.COOKIES[settings.CSRF_COOKIE_NAME]
立刻改成:
cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
这样就能直接从请求对象里拿到Cookie数据了。
2. 修复视图类的其他问题
你的networthChart视图类还有几个可以优化的地方,这些也可能是导致Forbidden错误的原因:
(1)多余的继承
APIView已经继承了View,不需要重复写class networthChart(APIView, View),改成:
class NetworthChart(APIView): # 顺便建议用大驼峰命名类,符合Python惯例
(2)认证与权限的矛盾
你设置了authentication_classes = []和permission_classes = [](允许匿名访问),但又在get方法里检查self.request.user.is_active——匿名用户的is_active永远是False,这会导致所有未登录用户都被返回403。
如果这个API需要用户登录才能访问:
- 删掉
authentication_classes和permission_classes的空列表配置,使用Django REST Framework默认的认证机制 - 把用户检查逻辑改成验证用户是否登录:
if not request.user.is_authenticated: # 用is_authenticated判断是否登录,而非is_active return HttpResponseForbidden("Not signed in")
如果这个API允许匿名访问:
- 直接删掉那个用户检查的
if语句即可
(3)正确使用@ensure_csrf_cookie装饰器
在类视图的方法上使用装饰器,需要用method_decorator包裹,否则装饰器不会生效:
from django.utils.decorators import method_decorator # 在get方法上添加装饰器 @method_decorator(ensure_csrf_cookie) def get(self, request, format=None): # 你的代码逻辑
3. 前端AJAX请求的优化
你已经写了获取CSRF Token的逻辑,但没有在$.ajax请求里用上。把CSRF Token加到请求头里:
$(document).ready(function(){ var endpoint = 'http://127.0.0.1:8000/api/networthchart/data/' var defaultData = [] var labels = [] $.ajax({ method:"GET", url: endpoint, headers: { 'X-CSRFToken': csrftoken }, // 新增这行,传递CSRF Token success: function(data){ labels = data.labels defaultData = data.default var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: [{ label: '# of Votes', data: defaultData, // 你的其他配置项 }] } }); }, // 建议添加错误回调,方便调试 error: function(xhr, status, error) { console.error("请求失败:", error); console.error("状态码:", xhr.status); } }); });
额外提醒:Django默认对GET请求不做CSRF验证,如果你只是做数据查询的GET请求,其实可以不用传递CSRF Token,之前的Forbidden错误大概率是因为视图里的用户检查逻辑导致的,而非CSRF问题。
内容的提问来源于stack exchange,提问作者Vardhan Mahajan

