angularcsvdjango-rest-frameworkexport-to-csvordereddict

Set Column order for modelSerializer output to CSV


CONTEXT

I'm trying to parse/filter a database using a Angular/Django rest framework and output the results to a CSV.

EXAMPLE DATA

id    name    hair    eye
1     John    Brown   Brown
2     Sharon  Blonde  Blue
4     Paul    Brown   Brown

PROBLEM

Whenever I run it and download the CSV, the column order is all jumbled up.

CURRENT CODE

VIEWS.PY
class PersonList(generics.ListAPIView):
serializer_class = PersonSerializers

def get_queryset(self):
    clientCode = self.kwargs['id']
    return Person.objects.filter(person_id=id)

@api_view(('GET',))
@renderer_classes((CSVRenderer,))
def download_csv_file(request, id):
    csv_file = Person.objects.filter(person_id=id)
    serializer = PersonSerializers(csv_file, many=True)
    return Response(serializer.data)

----------------------
SERIALIZERS.PY
class PersonSerializers(serializers.ModelSerializer):
class Meta:
    model = Person
    fields = ('__all__')
-------------
MODELS.PY
class Person(models.Model):
person_id = models.CharField(max_length=50, blank=True, null=True)
name = models.CharField(max_length=50, blank=True, null=True)
hair_color = models.CharField(max_length=50, blank=True, null=True)
eye_color = models.CharField(max_length=50, blank=True, null=True)

class Meta:
    managed = False
    db_table = 't_lov'

When I print serializer.data the result is:

[OrderedDict([('person_id', 1), ('name', 'John'), ('hair_color', 'brown'), ('eye_color', 'brown')]), OrderedDict([('person_id', 2), ('name', 'Sharon'), ('hair_color', 'Blonde'), ('eye_color', 'Blue')]), etc...

Solution

  • You can create a class and override the header attribute

    class MyUserRenderer (CSVRenderer):
        header = ['person_id','name','hair_color','eye_color']
    

    then use it in the renderer_classes

    @api_view(('GET',))
    @renderer_classes((MyUserRenderer ,))
    def download_csv_file(request, id):
        csv_file = Person.objects.filter(person_id=id)
        serializer = PersonSerializers(csv_file, many=True)
        return Response(serializer.data)
    

    I had the same problem and it worked for me.