csvs.py 2.92 KB
Newer Older
1 2 3 4 5 6 7
"""
Student and course analytics.

Format and create csv responses
"""

import csv
8

9 10 11 12 13 14 15 16 17
from django.http import HttpResponse


def create_csv_response(filename, header, datarows):
    """
    Create an HttpResponse with an attached .csv file

    header   e.g. ['Name', 'Email']
    datarows e.g. [['Jim', 'jim@edy.org'], ['Jake', 'jake@edy.org'], ...]
18 19 20 21

    The data in `header` and `datarows` must be either Unicode strings,
    or ASCII-only bytestrings.

22
    """
23
    response = HttpResponse(content_type='text/csv')
24
    response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
25 26 27 28 29 30
    csvwriter = csv.writer(
        response,
        dialect='excel',
        quotechar='"',
        quoting=csv.QUOTE_ALL)

reciproco committed
31 32 33
    encoded_header = [unicode(s).encode('utf-8') for s in header]
    csvwriter.writerow(encoded_header)

34 35 36
    for datarow in datarows:
        encoded_row = [unicode(s).encode('utf-8') for s in datarow]
        csvwriter.writerow(encoded_row)
37

38 39 40
    return response


41
def format_dictlist(dictlist, features):
42
    """
43 44 45 46 47 48 49 50
    Convert a list of dictionaries to be compatible with create_csv_response

    `dictlist` is a list of dictionaries
        all dictionaries should have keys from features
    `features` is a list of features

    example code:
    dictlist = [
51
        {
Miles Steele committed
52 53 54 55
            'label1': 'value-1,1',
            'label2': 'value-1,2',
            'label3': 'value-1,3',
            'label4': 'value-1,4',
56 57
        },
        {
Miles Steele committed
58 59 60 61
            'label1': 'value-2,1',
            'label2': 'value-2,2',
            'label3': 'value-2,3',
            'label4': 'value-2,4',
62 63 64
        }
    ]

65
    header, datarows = format_dictlist(dictlist, ['label1', 'label4'])
66

67 68 69 70 71
    # results in
    header = ['label1', 'label4']
    datarows = [['value-1,1', 'value-1,4'],
                ['value-2,1', 'value-2,4']]
    }
72 73
    """

74
    def dict_to_entry(dct):
75 76 77
        """ Convert dictionary to a list for a csv row """
        relevant_items = [(k, v) for (k, v) in dct.items() if k in features]
        ordered = sorted(relevant_items, key=lambda (k, v): header.index(k))
78
        vals = [v for (_, v) in ordered]
79 80
        return vals

81
    header = features
82 83
    datarows = map(dict_to_entry, dictlist)

84
    return header, datarows
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104


def format_instances(instances, features):
    """
    Convert a list of instances into a header list and datarows list.

    `header` is just `features` e.g. ['username', 'email']
    `datarows` is a list of lists, each sublist representing a row in a table
        e.g. [['username1', 'email1@email.com'], ['username2', 'email2@email.com']]
        for `instances` of length 2.

    `instances` is a list of instances, e.g. list of User's
    `features` is a list of features
        a feature is a string for which getattr(obj, feature) is valid

    Returns header and datarows, formatted for input in create_csv_response
    """
    header = features
    datarows = [[getattr(x, f) for f in features] for x in instances]
    return header, datarows