I have a working Django 1.8 site, and I want to add a RESTful API using django-rest-framework. I would like to support rendering to CSV and JSON formats, and am puzzling over how to do this.
In api/urls.py
I have this:
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'])
And I have this in 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)
But if I go to api/1.0/organisation.csv?code=123
, I still see:
format json
in the console.
What am I doing wrong? And how should I return CSV once I have managed to capture the format? (I suspect I'm probably doing the wrong thing by writing my own JSONResponse
, already.)
The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client. REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types.
Uploading CSV file: First create HTML form to upload the csv file. Use below code for the same. Important: Do not forget to include enctype="multipart/form-data" in form. Add a URL in URLpatterns.
django-csvimport is a generic importer tool to allow the upload of CSV files for populating data. The egg installs an admin csvimport model that has a file upload field. Add a new csvimport and upload a comma separated values file or MS Excel file.
If you just need to download CSV (without Model serialization etc)
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
This is an old post, but I've seen the accepted answer sets the CSVRenderer
as one of the defaults, which is not usually wanted.
I would implement the view this way:
...
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()
Of course, having the django-rest-framework-csv
installed and OrgSerializer
defined somewhere.
Then you can just set 'rest_framework.renderers.JSONRenderer'
as your default renderer in settings and the rest framework will automatically return csv content if you request it on the HTTP_ACCEPT
header - just for this view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With