mjumbewu / django-rest-framework-csv

CSV Tools for Django REST Framework
BSD 2-Clause "Simplified" License
364 stars 89 forks source link

Possibility to add headers ordering in the render method #27

Closed moumoutte closed 8 years ago

moumoutte commented 9 years ago

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

debnet commented 9 years ago

Please use OrderedDict for flattened lists and dicts, it keeps the order given by DRF.

An option in order to provide the headers' order will be gratefully accepted too!

freyley commented 9 years ago

:+1:

I also could really use ordering based on the serializer field definition.

tpeaton commented 9 years ago

:+1: for this feature.

moumoutte commented 9 years ago

I'll try a patch as soon as I have some time. Before the week-end I guess

travisbloom commented 8 years ago

:+1: was this ever implemented @moumoutte? would be really useful :)

moumoutte commented 8 years ago

Just add the order kwargs in render method, does it looks good to you ?

mjumbewu commented 8 years ago

Thanks @moumoutte for the pull request! It looks good, but I'm wondering whether it would be more useful if the order argument were an attribute on the class instead. I imagine myself using something like this in the following way:

class MyUserRenderer (CSVRenderer):
    order = ['first', 'last', 'email']

@api_view(['GET'])
@renderer_classes((MyUserRenderer,))
def my_view(request):
    users = User.objects.filter(active=True)
    content = [
        {'first': user.first_name, 'last': user.last_name, 'email': user.email}
        for user in users]
    return Response(content)

As a backup, it could be passed in with the renderer_context:

class MyView (APIView):
    renderer_classes = [CSVRenderer]

    def get_renderer_context(self):
        context = super().get_renderer_context()
        context['order'] = (
            self.request.GET['fields'].split(',') 
            if 'fields' in self.request.GET else None)
        return context

    ...
# Then I can specify field order as part of my request.
curl http://localhost:8000/api/my_view?fields=first,last,email

Either way, I feel like I don't call render directly from my code, so the keyword argument would be of limited use to me. Am I an outlier in that regard?

freyley commented 8 years ago

100% agree with mjumbewu about how I would use this.

mjumbewu commented 8 years ago

Actually, somehow I missed this, but it seems that what I described above (ordering with a class attribute) was introduced by @robguttman in pull request #3, commit 93236a0b2 (the attribute is called headers). Should be available since release 1.2.0

mjumbewu commented 8 years ago

I just released 1.4.0 which allows sorting fields using the header attribute on the CSVRenderer class, or using the "header" key in the renderer_context. I'm going to close this issue. Thanks @moumoutte for kicking off the thread!

debnet commented 8 years ago

It will also be good to override headers with a dict providing custom titles, is it possible?

mjumbewu commented 8 years ago

@debnet This is actually possible as of version 1.4.1 (released today! see pull request #39)