从django-rest-framework返回CSV格式?

Ric*_*ard 6 django django-rest-framework

我有一个工作的Django 1.8站点,我想使用django-rest-framework添加一个RESTful API。我想支持以CSV和JSON格式进行渲染,并且对如何做到这一点感到困惑。

api/urls.py我有这个:

from django.conf.urls import url, include
from rest_framework import routers
from rest_framework.urlpatterns import format_suffix_patterns
import views

router = routers.DefaultRouter()
urlpatterns = [
  url(r'^organisation/$', views.organisation), 
]
urlpatterns = format_suffix_patterns(urlpatterns,
                                 allowed=['json', 'csv'])
Run Code Online (Sandbox Code Playgroud)

我在api/views.py

class JSONResponse(HttpResponse):
    """
    An HttpResponse that renders its content into JSON.
    """
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

@api_view(['GET'])
def organisation(request, format=None):
    code = request.query_params.get('code', None)
    print 'format', format
    organisation = Organisation.objects.get(code=code)
    serializer = OrgSerializer(organisation)
    data = serializer.data
    return JSONResponse(data)
Run Code Online (Sandbox Code Playgroud)

但是,如果我去api/1.0/organisation.csv?code=123,我仍然会看到:

format json
Run Code Online (Sandbox Code Playgroud)

在控制台中。

我究竟做错了什么?设法捕获格式后,应该如何返回CSV?(我怀疑我可能JSONResponse已经通过写自己的东西做错了。)

nno*_*nov 10

这是一篇旧帖子,但我已经看到接受的答案将 设置CSVRenderer为默认值之一,这通常是不需要的。

我会以这种方式实现视图:

...
from rest_framework.viewsets import ModelViewSet
from rest_framework.settings import api_settings
from rest_framework_csv.renderers import CSVRenderer
from .... import OrgSerializer
...

class OrganizationViewSet(ModelViewSet):

    queryset = Organisation.objects.all()
    http_method_names = ['get', '...list all the other verbs you want']
    serializer_class = OrgSerializer
    renderer_classes = tuple(api_settings.DEFAULT_RENDERER_CLASSES) + (CSVRenderer,)

    def get_queryset(self):
        if 'code' in self.request.GET:
            code = self.request.GET['code']
            return Organisation.objects.filter(code=code)
        return Organisation.objects.all()
Run Code Online (Sandbox Code Playgroud)

当然,在某处django-rest-framework-csv安装和OrgSerializer定义。

然后,您可以在设置'rest_framework.renderers.JSONRenderer'中将其设置为默认渲染器,如果您在HTTP_ACCEPT标题中请求它,其余框架将自动返回 csv 内容-仅用于此视图

  • 如何使用此实现定义自定义标头? (2认同)
  • @PedroHenrique如果你想设置我提到的HTTP_ACCEPT标头,请尝试运行django单元测试并定义:HTTP_ACCEPT='text/csv'。这适用于 ApiTestCase 子类 (DRF)。如果您想使用 Accept 标头调用此视图,只需遵循标准:https://developer.mozilla.org/es/docs/Web/HTTP/Headers/Accept (2认同)

Art*_*kyi 9

如果您只需要下载 CSV(没有模型序列化等)

import csv
from django.http import HttpResponse
from rest_framework.views import APIView


class CSVviewSet(APIView):

    def get(self, request, format=None):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="export.csv"'
        writer = csv.DictWriter(response, fieldnames=['emp_name', 'dept', 'birth_month'])
        writer.writeheader()
        writer.writerow({'emp_name': 'John Smith', 'dept': 'Accounting', 'birth_month': 'November'})
        writer.writerow({'emp_name': 'Erica Meyers', 'dept': 'IT', 'birth_month': 'March'})
        return response
Run Code Online (Sandbox Code Playgroud)


Ric*_*ard 7

知道了。诀窍是安装djangorestframework-csv,然后在设置中添加以下内容:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework_csv.renderers.CSVRenderer',
    ),
}
Run Code Online (Sandbox Code Playgroud)

然后废弃该JSONResponse函数views.pyreturn Response(serializer.data)改为执行。最后非常容易。