基于Django REST Framework创建JSON与CSV API遇问题求助
解决JSON API浏览器访问问题与CSV导出API实现方案
嘿,看来你在Django REST Framework里搞两个API遇到了点小麻烦——JSON API能被Ajax调用但浏览器直接访问出问题,CSV导出API也卡壳了。我来帮你一步步捋清楚:
一、先搞定JSON API的浏览器访问问题
你说Ajax能正常拿数据,但浏览器直接打开API地址不行,大概率是渲染器配置在搞鬼。ModelViewSet默认自带BrowsableAPIRenderer,浏览器访问时会优先返回那种带表单的可浏览HTML页面,而不是纯JSON。如果想让浏览器直接访问也返回JSON,你可以给视图集指定只保留JSON渲染器:
from rest_framework.renderers import JSONRenderer class VideoViewSet(viewsets.ModelViewSet): queryset = DatamsVideos.objects.all() serializer_class = VideosSerializer # 强制只返回JSON格式,浏览器访问也会直接拿到JSON renderer_classes = [JSONRenderer] # 你的CSVParser可以保留,用来处理客户端发过来的CSV请求(如果有需要的话) parser_classes = (CSVParser,) + tuple(viewsets.ModelViewSet.parser_classes)
另外也可能是权限认证的锅——比如你的视图集加了权限类,浏览器访问时没带认证信息,导致返回403/401。开发阶段可以先临时把权限改成AllowAny排查下:
from rest_framework.permissions import AllowAny class VideoViewSet(viewsets.ModelViewSet): # ... 其他配置不动 permission_classes = [AllowAny]
还有别忘了检查路由配置,确保用DefaultRouter正确注册了视图集:
from rest_framework.routers import DefaultRouter from .views import VideoViewSet router = DefaultRouter() router.register(r'videos', VideoViewSet) urlpatterns = router.urls
二、实现CSV导出API
你已经加了CSVParser,但要注意——这个是用来解析客户端发给你的CSV请求的,而导出CSV需要的是给客户端返回CSV格式的响应,所以得用CSVRenderer,再给视图集加个自定义动作专门处理导出:
步骤1:修改视图集代码
from rest_framework.renderers import CSVRenderer, JSONRenderer from rest_framework.decorators import action from rest_framework.response import Response class VideoViewSet(viewsets.ModelViewSet): queryset = DatamsVideos.objects.all() serializer_class = VideosSerializer # 同时支持JSON和CSV两种响应格式 renderer_classes = [JSONRenderer, CSVRenderer] parser_classes = (CSVParser,) + tuple(viewsets.ModelViewSet.parser_classes) # 自定义导出CSV的动作,detail=False表示这是列表级别的动作 @action(detail=False, methods=['get'], renderer_classes=[CSVRenderer]) def export_csv(self, request): # 获取要导出的数据集 queryset = self.get_queryset() # 如果需要过滤数据,可以从请求参数里拿条件,比如按状态过滤 status = request.query_params.get('status') if status: queryset = queryset.filter(status=status) # 序列化数据 serializer = self.get_serializer(queryset, many=True) # 构造响应,设置下载文件名 response = Response(serializer.data) response['Content-Disposition'] = 'attachment; filename="videos.csv"' return response
步骤2:访问导出接口
用DefaultRouter的话,这个自定义动作会自动生成路由,直接访问/videos/export_csv/就能下载CSV文件了。
小提醒
如果你的序列化器里有嵌套字段(比如关联了其他模型),CSV是不支持嵌套结构的,得用SerializerMethodField把嵌套数据转成字符串,比如:
class VideosSerializer(serializers.ModelSerializer): category_name = serializers.SerializerMethodField() def get_category_name(self, obj): return obj.category.name # 假设关联了Category模型 class Meta: model = DatamsVideos fields = ['id', 'title', 'category_name', 'created_at']
三、报错排查小技巧
如果还是搞不定,试试这些方法:
- 打开浏览器控制台,看网络请求的状态码和响应内容,比如是不是404、403或者500
- 看Django的日志文件,服务器端的报错信息会写在里面,能帮你定位问题
- 确保
rest_framework已经加到INSTALLED_APPS里了
内容的提问来源于stack exchange,提问作者Omega
相关产品推荐
相关产品推荐

