我有一个有效的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'])
我在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)
但如果我去api/1.0/organisation.csv?code=123
,我仍然会看到:
format json
在控制台中。
我做错了什么?一旦我设法捕获格式,我该如何返回CSV? (我怀疑我可能已经通过编写自己的JSONResponse
来做错了。)
答案 0 :(得分:4)
知道了。诀窍是安装djangorestframework-csv,然后在设置中添加以下内容:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
'rest_framework_csv.renderers.CSVRenderer',
),
}
然后废弃JSONResponse
中的views.py
功能,而只是执行return Response(serializer.data)
。最后很容易。
答案 1 :(得分:2)
这是旧文章,但是我已经看到接受的答案将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()
当然,要安装django-rest-framework-csv
并在某处定义OrgSerializer
。
然后,您可以在设置中将'rest_framework.renderers.JSONRenderer'
设置为默认渲染器,如果您在HTTP_ACCEPT
标头上请求它,其余框架将自动返回csv内容-仅用于此视图。
答案 2 :(得分:1)
我认为StreamingHttpResponse
应该是首选方式。使用django-storages
和ViewSet
时,看起来或多或少都是这样。
@action(detail=True, methods=["get"])
def download(self, request, pk=None):
f = self.get_object()
response = StreamingHttpResponse(
streaming_content=f.file.chunks(), content_type="text/csv"
)
response[
"Content-Disposition"
] = f'attachment; filename="{f.name}.csv"'
response.status_code = status.HTTP_200_OK
return response
此外,FileResponse
基本上是一个带有某些标头等的StreamingHttpResponse
,因此对于本用例来说,两者都是很好的选择。
答案 3 :(得分:0)
如果您只需要下载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