Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning CSV format from django-rest-framework?

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.)

like image 753
Richard Avatar asked Aug 22 '15 20:08

Richard


People also ask

What is renderers in Django REST framework?

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.

How import and read CSV file in Django?

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.

What is csv file in Django?

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.


2 Answers

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
like image 118
Artem Bernatskyi Avatar answered Sep 22 '22 03:09

Artem Bernatskyi


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.

like image 30
nnov Avatar answered Sep 21 '22 03:09

nnov