Code Monkey home page Code Monkey logo

django-rest-framework-csv's Introduction

djangorestframework-csv

build status_

CSV Tools for Django REST Framework

Installation

$ pip install djangorestframework-csv

Compatibility

  • For compatibility with Python 3 and Django < 3.2, use djangorestframework-csv<3.0.1
  • For compatibility with Python 2.7, use djangorestframework-csv<3

Usage

views.py

from rest_framework.views import APIView
from rest_framework.settings import api_settings
from rest_framework_csv import renderers as r

class MyView (APIView):
    renderer_classes = (r.CSVRenderer, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)
    ...

Alternatively, to set CSV as a default rendered format, add the following to the settings.py file:

REST_FRAMEWORK = {
    # specifying the renderers
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework_csv.renderers.CSVRenderer',
    ),
}

Ordered Fields

By default, a CSVRenderer will output fields in sorted order. To specify an alternative field ordering you can override the header attribute. There are two ways to do this:

  1. Create a new renderer class and override the header attribute directly:

    class MyUserRenderer (CSVRenderer):
        header = ['first', 'last', 'email']
    
    @api_view(['GET'])
    @renderer_classes((MyUserRenderer,))
    def my_view(request):
        users = User.objects.filter(is_active=True)
        content = [{'first': user.first_name,
                    'last': user.last_name,
                    'email': user.email}
                   for user in users]
        return Response(content)
  2. Use the renderer_context to override the field ordering on the fly:

    class MyView (APIView):
        renderer_classes = [CSVRenderer]
    
        def get_renderer_context(self):
            context = super().get_renderer_context()
            context['header'] = (
                self.request.GET['fields'].split(',')
                if 'fields' in self.request.GET else None)
            return context
    
        ...

Labeled Fields

Custom labels can be applied to the CSVRenderer using the labels dict attribute where each key corresponds to the header and the value corresponds to the custom label for that header.

1) Create a new renderer class and override the header and labels attribute directly:

class MyBazRenderer (CSVRenderer):
    header = ['foo.bar']
    labels = {
        'foo.bar': 'baz'
    }

Pagination

Using the renderer with paginated data is also possible with the new PaginatedCSVRenderer class and should be used with views that paginate data

For more information about using renderers with Django REST Framework, see the API Guide or the Tutorial.

Running the tests

To run the tests against the current environment:

$ ./manage.py test

Changelog

3.0.2

  • Fix the project long description metadata

3.0.1

  • Remove Django tests for all but the currently supported Django versions (3.2, 4.1, 4.2). Also only keep tests for Python versions compatible with supported Django versions (3.8 - 3.11).

3.0.0

  • Removed compatibility with Python 2
  • Added compatibility with Django up to 3.2 and 4.2 (thanks to work from @TTycho, @awais786, @arpitjain799, @tirkarthi)

2.1.1

  • Add support for byte order markers (BOM) (thanks @Yaoxin)
  • Documentation updates (thanks @rjemanuele and @coreyshirk)

2.1.0

  • CSVs with no data still output header labels (thanks @travisbloom)
  • Include a paginated renderer as part of the app (thanks @masterfloda)
  • Generators can be used as data sources for CSVStreamingRenderer (thanks @jrzerr)
  • Support for non UTF-8 encoding parsing (thanks @weasellin)

2.0.0

  • Make CSVRenderer.render return bytes, and CSVParser.parse expect a byte stream.
  • Have data-less renders print header row, if header is explicitly supplied
  • Drop Django 1.7 tests and add Django 1.10 tests
  • have CSVRenderer.tableize act as a generator when possible (i.e., when a header is explicitly specified).
  • Add docs for labels thanks to @radyz
  • Fix header rendering in CSVStreamingRenderer thanks to @radialnash
  • Improve unicode handling, thanks to @brandonrobertz

1.4.0/1.4.1

  • Add support for changing field labels in the CSVRenderer, thanks to @soby
  • Add support for setting CSVRenderer headers, labels, and writer_opts as renderer_context parameters.
  • Renamed CSVRenderer.headers to CSVRenderer.header; old spelling is still available for backwards compatibility, but may be removed in the future.

1.3.4

  • Support streaming CSV rendering, via @ivancrneto
  • Improved test configuration and project metadata, via @ticosax

1.3.2/1.3.3

  • Support unicode CSV parsing, and universal newlines, with thanks to @brocksamson

1.3.1

  • Renderer handles case where data is not a list by wrapping data in a list, via pull request from @dougvk
  • Better cross Python version support, via @paurullan and @vishen

1.3.0

  • Support for Python 3, derived from work by @samdobson

1.2.0

  • Support consistent ordering of fields in rendered CSV; thanks to @robguttman
  • Support specifying particular fields/headers in custom CSV renderer by overriding the headers attribute.

1.1.0

  • Support simple CSV parsing; thanks to @sebastibe

1.0.1

  • Add the package manifest

1.0.0

  • Initial release

django-rest-framework-csv's People

Contributors

alukach avatar ammattm avatar arpitjain799 avatar awais786 avatar brandonrobertz avatar brocksamson avatar coreyshirk avatar dougvk avatar ivancrneto avatar jrzerr avatar masterfloda avatar mjumbewu avatar moumoutte avatar paurullan avatar radialnash avatar radyz avatar rjemanuele avatar rouge8 avatar samdobson avatar scotta avatar sebastibe avatar soby avatar ticosax avatar tirkarthi avatar tomchristie avatar travisbloom avatar ttycho avatar vishen avatar weasellin avatar yaoxin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-rest-framework-csv's Issues

Add support Django 3.2

In OpenedX the libraries are being upgraded to migrate to Django 3.2, I would like to add the necessary changes in the tests to ensure it.

I did a PR #89 , I would like to know your opinion and if something else is needed to support Django 3.2

__pycache__ cotains bad .pyc files

Using buildout or easy_install with version 1.3.3 of django-rest-framework-csv does not work.

$ easy_install ./djangorestframework-csv-1.3.3.tar.gz
Processing djangorestframework-csv-1.3.3.tar.gz
Writing /tmp/easy_install-uIm5K5/djangorestframework-csv-1.3.3/setup.cfg
Running djangorestframework-csv-1.3.3/setup.py -q bdist_egg --dist-dir /tmp/easy_install-uIm5K5/djangorestframework-csv-1.3.3/egg-dist-tmp-rLRvvm
zip_safe flag not set; analyzing archive contents...
Traceback (most recent call last):
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/bin/easy_install", line 11, in
sys.exit(main())
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1909, in main
with_ei_usage(lambda:
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1896, in with_ei_usage
return f()
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1913, in
distclass=DistributionWithoutHelpCommands, **kw
File "/usr/lib/python2.7/distutils/core.py", line 151, in setup
dist.run_commands()
File "/usr/lib/python2.7/distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/usr/lib/python2.7/distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 358, in run
self.easy_install(spec, not self.no_deps)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 574, in easy_install
return self.install_item(None, spec, tmpdir, deps, True)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 623, in install_item
dists = self.install_eggs(spec, download, tmpdir)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 809, in install_eggs
return self.build_and_install(setup_script, setup_base)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1015, in build_and_install
self.run_setup(setup_script, setup_base, args)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1000, in run_setup
run_setup(setup_script, args)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/sandbox.py", line 50, in run_setup
lambda: execfile(
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/sandbox.py", line 100, in run
return func()
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/sandbox.py", line 52, in
{'file':setup_script, 'name':'main'}
File "setup.py", line 86, in
File "/usr/lib/python2.7/distutils/core.py", line 151, in setup
dist.run_commands()
File "/usr/lib/python2.7/distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/usr/lib/python2.7/distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/bdist_egg.py", line 232, in run
os.path.join(archive_root,'EGG-INFO'), self.zip_safe()
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/bdist_egg.py", line 271, in zip_safe
return analyze_egg(self.bdist_dir, self.stubs)
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/bdist_egg.py", line 407, in analyze_egg
safe = scan_module(egg_dir, base, name, stubs) and safe
File "/home/onjin/.virtualenvs/tmp-cace28362d13d1a3/local/lib/python2.7/site-packages/setuptools/command/bdist_egg.py", line 438, in scan_module
code = marshal.load(f); f.close()
ValueError: bad marshal data (unknown type code)

After removing pycache folder everything works again

XLSParser

And here is the parser:
parsers.py

import xlrd

class HierarchicalXLSParser(HierarchicalCSVParser):
    """
    Parses CSV serialized data.

    The parser assumes the first line contains the column names.
    """

    media_type = 'application/vnd.ms-excel'

    def parse(self, stream, media_type=None, parser_context=None):
        book = xlrd.open_workbook(file_contents=stream)
        sheet = book.sheet_by_index(0)

        data = []
        header = []
        try:
            for row_index in range(sheet.nrows):
                row = []
                for col_index in range(sheet.ncols):
                    if row_index==0:
                        header.append(sheet.cell(row_index,col_index).value)
                    else:
                        row.append(sheet.cell(row_index,col_index).value)
                if row_index!=0:
                    row_data = dict(zip(header, row))
                    hierarchical_data = self._csv_convert(row_data)
                    data.append(hierarchical_data)
            return data
        except Exception as exc:
            raise ParseError('HierarchicalXLS parse error - %s' % str(exc))

Unicode issues in production (with wsgi)

For parsing, unicode all works great in the unit tests, but there's one huge problem: in the unit tests the stream object passed to CSVParser.parse is a StringIO, while in production (apache/wsgi) it's actually an instance of <class 'django.core.handlers.wsgi.WSGIRequest'>. The end result is the unit test pass, showing unicode success, but when you POST some unicode to an endpoint using the parser you get the dreaded:

{"detail":"CSV parse error - 'ascii' codec can't decode byte 0xe2 in position 17136: ordinal not in range(128)"}

I wrote a stopgap hotfix in a fork (https://github.com/alertmedia/django-rest-framework-csv), but it breaks all the unit tests, which are written using the StringIO streams. I also used unicodecsv library, not builtin csv.

Any ideas on reconciliation here?

Document data.header

The Ordered Fields section of the documentation should mention this third method which is supported by the renderer:

        # Try to pull the header off of the data, if it's not passed in as an
        # argument.
        if not header and hasattr(data, 'header'):
            header = data.header

This can be accomplished by using a subclass of list:

class AttributeList(list):
    """A list which can have attributes added."""

alist = AttributeList(rows_list)
alist.header = column_names_list
return Response(alist)

response['Content-Type'] not set

Is it an issue with my code or a bug of django-rest-framework-csv?

class DataList(generics.ListAPIView):
    ...
    renderer_classes = [CSVRendererWithUnderscores, ]
    ...
    def finalize_response(self, request, response, *args, **kwargs):
        response = super(DataList, self)\
            .finalize_response(request, response, *args, **kwargs)
        response['Content-Disposition'] = \
            "attachment; filename=data_{:s}.csv"\
            .format(kwargs['year'])
        return response

Adding response['content-type'] = 'text/csv' wouldn't help.

Potential compatibility issue / style improvement

render method on the main renderer is defined like this: def render(self, data, media_type=None, renderer_context={}, writer_opts=None): here which is both not how other renderers are defined and has a mutable object as a default value which is discouraged and could be dangerous.

I suggest we update it to something closer to other examples in DRF: def render(self, data, accepted_media_type=None, renderer_context=None). I'll prepare a PR if there are no volunteers or objections.

Output CSV without header

How do I output CSV without a header, if I make the header None, no data is rendered.

I've tried:

class HeaderlessRenderer(csvrenderer.CSVRenderer):
    header = None

@api_view(['GET'])
@renderer_classes((HeaderlessRenderer))
def infosheet(request, analysisid, **kwargs):
    ....

Hierarchical parser

Hi,
When rendering a hierarchical structure, the renderer works fine and the name
of the columns are:
level.N.sublevel
But the parser does not take this structure in account. Instead, it just takes the names
of the columns and put the values, all in a flat structure.
I suggest the following code to recover the hierarchical structure:

class HierarchicalCSVParser(BaseParser):
    """
    Parses CSV serialized data into hierarchical structure.

    The parser assumes the first line contains the column names.
    """

    media_type = 'text/csv'

    def parse(self, stream, media_type=None, parser_context=None):
        parser_context = parser_context or {}
        delimiter = parser_context.get('delimiter', ',')

        try:
            encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
            rows = unicode_csv_reader(universal_newlines(stream), delimiter=delimiter, charset=encoding)
            data = OrderedRows(next(rows))
            for row in rows:
                row_data = dict(zip(data.header, row))
                hierarchical_data = self._csv_convert(row_data)
                data.append(hierarchical_data)
            return data
        except Exception as exc:
            raise ParseError('CSV parse error - %s' % str(exc))

    def _csv_convert(self,flat_data):
        first_level_keys = {key.split(".")[0] for key in flat_data.keys()}
        if list(first_level_keys)[0].isdigit():
            d = []
        else:
            d = {}
        for first_level_key in first_level_keys:                
            # a subset of the dictionary with only the entries with the
            # key: first_level_key.* and non empty value
            subset = {key:value for key, value in flat_data.items() if key.partition(".")[0]==first_level_key and len(value)>0}
            if len(subset) > 0:
                at_deepest = subset.keys()[0].partition(".")[1]==''
                if at_deepest:
                    # end of recursivity
                    d.update(subset)
                else:
                    # can go deeper
                    # remove the first_level_key 
                    flat_second_level_subset = {key.partition(".")[2]:value for key, value in subset.items()}
                    second_level_subset = self._csv_convert(flat_second_level_subset)
                    if first_level_key.isdigit():
                        # add to the list
                        d.append(second_level_subset)
                    else:
                        # add to the dictionary
                        d[first_level_key] = second_level_subset

        return d

Francesc

CSVStreamingRenderer Example

Hey there, I am trying to implement a streaming CSV renderer within a list API view and am having trouble with the code provided in renderers.py. Is it possible to get a full example in example/views.py that shows its usage?

Column names from verbose names

Since Django provides Fields a verbose_name attribute, it would be nice if that could be specified as the column name. This messes up the flattening maybe though...

Customize file name

Is there a place to specify a filename or something I can override to tell the renderer which file name to use? I looked at the source and I could not find the place where to speficify this. Thanks.

Releases potentially causing the project to appear unmaintained

Hi @mjumbewu and team, I wanted to let you know it took me a bit to realize that this project is under active development since the latest "release" was 1.3.3 and that's what GitHub decides to show on the front page on the right side. After seeing the latest commit was from May, I checked the tags and saw there have been a number of new versions since 1.3.3.

I'm not sure of the best solution here, but wanted to raise the issue since it's probably difficult to notice if you're a regular contributor.

Screenshot from 2021-08-04 13-53-20

NewLine Header

Is there a way to archieve header like this?? Thanks...

Screenshot_20200808_161446

Is this project still active?

It looks like this project isn't being maintained anymore and there are several significant bugs in the mainline version. Just trying to get a pulse on the project here, as we depend on this in production and are trying to avoid straight up forking it.

CSV Post generates error

I run this through a terminal:

curl -X POST -d @C://Users/johnecon/Downloads/participants.csv -H "Authorization: Token b6b904232cb4abb86ba3e01e299110df9d4c83a4" -H "Content-Type: text/csv" localhost:8000/api/config

This is my view in listening in api/config

from rest_framework.decorators import api_view, authentication_classes, parser_classes
from rest_framework_csv import parsers as p
@api_view(['POST'])
@authentication_classes((authentication.BasicAuthentication, authentication.TokenAuthentication))
@parser_classes([p.CSVParser])
def CsvConfig(request):
    f = request.FILES
    return Response({"success": True})

The error I am getting:

{"detail":"CSV parse error - iterator should return strings, not bytes (did you open the file in text mode?)"}

I am using python 3.4.2 django 1.7

This is how my csv looks when I edit it:

First Name|Last Name|Username|Project|SubProject|Role|Phone|Skype
Andreas Kær,Eriksen,s133998,02264F15,1A,Leader,,skype_1
Ernst Magnus,Nylander,s122176,02264F15,1A,Contibutor,,skype_2
Mike Østergaard,Behrens,s133987,02264F15,1B,Leader,,skype_28

Any help would be highly appreciated :)

Field order doesnt respected

When i have a serializer with a defined field list like this:

 class Meta:
     model = ExternalLink
     fields = ('date', 'linked_by', 'domain', 'trust_flow', 'citation_flow', 'backlink_number')

I expected the output of csv to be in the same order. But this doesnt happen.

Is it possible to use StreamingHttpResponse?

We are currently using django-rest-framework-csv for csv export, but we have found we have some large datasets that eventually lead to a timeout between nginx and our app. Is it possible to use StreamingHttpResponse for returning a csv file using this library?

Generator objects cannot be passed into CSVStreamingRenderer

CSVStreamingRenderer is great, it works as a generator along with tabelize which also works as a generator. However, you cannot pass a Generator object in as your data to be rendered. This code in CSVStreamingRenderer causes the issue:

        if not isinstance(data, list):
            data = [data]

A generator object is not a type list, so the if statement evaluates to true so this code breaks the renderer for a Generator object.

I have successfully used this with a generator as the data source by changing that to:

        if not isinstance(data, GeneratorType) and not isinstance(data, list):
            data = [data]

PR on it's way...

Field Order / Headers from the Serializer

Is it possible to get the the serializer that is the CSVRenderer is rendering to use its fields attribute to specify the header ordering?

I'm trying to figure out if I can do that to define the ordering in a single place?

XLS support

Hi, I noticed, that this repo has pull request #29 with xls support. But there is some little problem with testing. Is some hope that it will be merged? Thanks.

There is an issue with the Renderer.py it seems like its not passing the headers when called from CSVStreamingRender

In renderer Line #73
needs to be >>>>
data.header = self.header or data.header

... Reason as header will always be none

Following Snippet of code fails, you seem to have it provided for streaming renderer. Ive fixed the bug locally

renderer = CSVStreamingRenderer()
renderer.header = ['customer','name','etc']
from django.http import StreamingHttpResponse
filename = 'some_report_{:%Y-%m-%d}'.format(timezone.now())
response = StreamingHttpResponse(renderer.render(content), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="' + filename + '.csv"'

line breaks inside quoted fields are lost

When the CSV input contains line breaks inside quoted fields, like so:

c1,c2
foo,"bar
baz"

the parser drops the interior line breaks, yielding

{ 'c1': 'foo', 'c2': 'barbaz' }

rather than the expected

{ 'c1': 'foo', 'c2': 'bar\r\nbaz' }

That's with Python 2.7.6, REST Framework 2.4.3, and Django 1.5.8 on
Linux.

I was able to fix this by changing splitlines() to splitlines(True) in
parsers.py.

Fields format

Hi,

It is possible format the fields (i.e. datetime fields)?

Thanks

IE11 Does not Download CSV, Chrome on Windows saves file as ".txt"

There seems to be some mime-type/content-type issues with this renderer. On my Mac, I have no issues, however Windows users experience problems with both Chrome and IE11. On Chrome, the file is downloaded without an extension, and on IE11, the contents are just rendered to the browser.

Setting a filename

Calling the api with ?format=csv makes you download a file, which is great.

Is there a simple way to set what the filename will be?

Expose Sorting Function

In the case I’m currently working on, I don’t know (and have no easy way to retrieve) all CSV headers in advance. It’d be great if this library would expose an overridable def sort_headers method.

Possible bug: '?format=csv' is appended to URLs in the downloaded CSV

We are with the last version using the PaginatedCSVRenderer, specified in the settings. CSVs are not correctly downloaded if we either put 'format=csv' in the query string or use the drop-down menu for choosing the format in the browsable API; then '?format=csv' is appended to the URLs in the downloaded CSVs - using hyperlinked serializers. URLs are correct if we specify 'text/csv' in the accept header and not in the query string.

Problem importing CSVRenderer

I get an error message when trying to import this package. I'm using Django 1.5, and have django-rest-framework and django-rest-framework-csv installed. I've added both to my INSTALLED_APPS, When I run these lines:

from rest_framework.views import APIView from rest_framework.settings import api_settings from rest_framework_csv import CSVRenderer

This line:
from rest_framework_csv import CSVRenderer
gives an error message:
"ImportError: cannot import name CSVRenderer"

However,
from rest_framework_csv import * works fine

Argument errror

Hi,

I've started seeing this error in 1.4.1:

  File "/opt/glow/envs/glowmachine_env/local/lib/python2.7/site-packages/rest_framework/response.py", line 63, in rendered_content
    ret = renderer.render(self.data, media_type, context)
  File "/opt/glow/envs/glowmachine_env/local/lib/python2.7/site-packages/rest_framework_csv/renderers.py", line 51, in render
    table = self.tablize(data, header=header, labels=labels)
TypeError: tablize() got an unexpected keyword argument 'header'

newline handling in restframework csv

Hi,
As I understand csv parser removes newline characters here: https://github.com/mjumbewu/django-rest-framework-csv/blob/master/rest_framework_csv/parsers.py#L25-L26

Lets say there a cell in csv where value is something like:
'''
Nature
Foliage
Trees
'''

Now we want to parse this particular cell as ["Nature", "Foliage", "Trees"] But with current parser code we can't? because after splitlines() the cell becomes "NatureFoliageTrees"?

Is there a way to handle the issue I am facing?

Possibility to add headers ordering in the render method

Actually, it's pretty difficult to maintain a renderer with ordering columns when the columns are generated dynamicaly. It will be nice to have a way to override the headers attributes on the single instance at the render time.

def render(self, headers=None, *args, **kwargs):
    if headers:
        self.headers = headers
     # Do the rendering

With this patch , we can have two way to fill up the headers values, it will be very helpful.

If you want I can write a patch

Documentation Error

Hi,

In the file views.py I think It should be like this:

renderer_classes = (r.CSVRenderer, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)

TypeError: can only concatenate tuple (not "list") to tuple

Is your README example correct?

Had to replace this line
(csv_render.CSVRenderer, ) + api_settings.DEFAULT_RENDERER_CLASSES

with this one
(csv_render.CSVRenderer, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)

TypeError: can only concatenate tuple (not "list") to tuple

XLSRenderer

Hi,
In order to render as XLS file, the following code could be used:
renderers.py

import xlwt
from datetime import datetime, date

class XLSRenderer(CSVRenderer):
    media_type = 'application/ms-excel'
    format = 'xls'

    def render(self, data, media_type=None, renderer_context=None, sheetname='First'):       
        table = self.tablize(data)
        wb = self.to_workbook(table, sheetname=sheetname)
        return wb

    # source: http://fragmentsofcode.wordpress.com/2009/10/09/xlwt-convenience-methods/
    def to_workbook(self, tabular_data, workbook=None, sheetname=None):
        """
        Returns the Excel workbook (creating a new workbook
        if necessary) with the tabular data written to a worksheet
        with the name passed in the 'sheetname' parameter (or a
        default value if sheetname is None or empty).
        """
        wb = workbook or xlwt.Workbook(encoding='utf8')
        if len(sheetname)>31:
            sheetname = sheetname[:31]
        ws = wb.add_sheet(sheetname or 'Data')
        self.to_worksheet(tabular_data, ws)
        return wb


    def to_worksheet(self, tabular_data, worksheet):
        """
        Writes the tabular data to the worksheet (returns None).
        Thanks to John Machin for the tip on using enumerate().
        """

        default_style = xlwt.Style.default_style
        datetime_style = xlwt.easyxf(num_format_str='dd/mm/yyyy hh:mm')
        date_style = xlwt.easyxf(num_format_str='dd/mm/yyyy')

        for row, rowdata in enumerate(tabular_data):
            worksheet_row = worksheet.row(row)
            for col, val in enumerate(rowdata):
                if isinstance(val, datetime):
                    val = val.replace(tzinfo=None)
                    style = datetime_style
                elif isinstance(val, date):
                    style = date_style
                else:
                    style = default_style

                worksheet_row.write(col, val, style=style) 

A usage example to export several items from admin:
admin.py

from datetime import datetime
from django.utils.translation import ugettext_lazy as _

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    model = MyModel
    actions = ['export_xls_from_admin_view']

    def export_xls_from_admin_view(self, request, queryset):
        serializer = MyModelSerializer(queryset, many=True)
        wb = XLSRenderer().render(serializer.data, sheetname='MyModel')

        now = datetime.now()
        filename = "mymodel_%s.xls" % (now.strftime('%Y%m%d-%H%M%S'))

        # Django < 1.7
        #response = HttpResponse(mimetype="application/ms-excel")
        # Django 1.7
        response = HttpResponse(content_type="application/ms-excel")
        response['Content-Disposition'] = 'attachment; filename=%s' % filename
        wb.save(response)

        return response
    export_xls_from_admin_view.short_description = _("Export selected items to XLS")

Francesc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.