summaryrefslogtreecommitdiff
path: root/lib/grappelli/actions.py
blob: d49c31792073922487a1ae02813ef5826c3f0a80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# coding: utf-8

# PYTHON IMPORTS
from datetime import datetime
import csv
import re
from types import *

# DJANGO IMPORTS
from django.contrib.admin import helpers
from django.utils.encoding import force_unicode
from django.shortcuts import render_to_response
from django import template
from django.contrib.admin.util import unquote
from django.http import HttpResponse
from django.utils.translation import ugettext as _


def get_csv_export_fields(modeladmin, included):
    """
    Return a sequence of tuples which should be included in the export.
    """
    model_fields = [f.name for f in modeladmin.model._meta.fields]
    #for relation in modeladmin.csv_follow_relations:
    #    for field in modeladmin.model._meta.get_field_by_name(relation)[0].rel.to._meta.fields:
    #        fields.append([relation, field.name])
    fields = []
    for item in modeladmin.list_display:
        if item != "action_checkbox":
            if csv_get_fieldname(item) in included:
                fields.append(item)
            elif isinstance(item, FunctionType) and (item.__name__ in included):
                fields.append(item)
    
    for f in model_fields:
        if (csv_get_fieldname(f) in included) and (csv_get_fieldname(f) not in fields):
            fields.append(f)
    return fields


def get_csv_export_field_names(modeladmin):
    model_fields = [f for f in modeladmin.model._meta.fields]
    #for relation in modeladmin.csv_follow_relations:
    #    for field in modeladmin.model._meta.get_field_by_name(relation)[0].rel.to._meta.fields:
    #        fields.append([relation, field.name])
    fields = []
    for item in modeladmin.list_display:
        if isinstance(item, FunctionType):
            fields.append([item.__name__, item.short_description])
        elif item != "action_checkbox":
            appended = False
            for f in model_fields:
                if f.name == item:
                    fields.append([f.name, f.verbose_name])
                    appended = True
                    break
            if not appended:
                fields.append([item, item])
    
    for f in model_fields:
        inserted = False
        for item in fields:
            if item[0] == f.name:
                inserted = True
                break
        if not inserted:
            fields.append([f.name, f.verbose_name])
    return fields


def csv_get_export_filename(modeladmin):
    ts = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
    return '%s_%s_%s_export.csv' % (ts, modeladmin.model._meta.app_label, modeladmin.model._meta.module_name)


def csv_resolve_field(row, fieldname):
    if isinstance(fieldname, basestring):
        if isinstance(getattr(row, fieldname), MethodType):
            return getattr(row, fieldname)()
        else:
            return getattr(row, fieldname)
    elif isinstance(fieldname, FunctionType):
        return fieldname(row)
    else:
        obj = row
        for bit in fieldname:
            obj = getattr(obj, bit)
        return obj


def csv_get_fieldname(field):
    if isinstance(field, basestring):
        return field
    elif isinstance(field, FunctionType):
        return field.short_description
    return '.'.join(field)


def csv_export_selected(modeladmin, request, queryset):
    if request.POST.get('post'):
        csv_export_url = '~csv/'
        csv_export_dialect = 'excel'
        #csv_follow_relations = []
        csv_export_fmtparam = {
           'delimiter': ';',
           'quotechar': '"',
           'quoting': csv.QUOTE_MINIMAL,
        }
        fields = get_csv_export_fields(modeladmin, request.POST.getlist('_fields'))
        headers = [csv_get_fieldname(f) for f in fields]
        
        response = HttpResponse(mimetype='text/csv')
        response['Content-Disposition'] = 'attachment; filename=%s' % csv_get_export_filename(modeladmin)
        writer = csv.writer(response, csv_export_dialect, **csv_export_fmtparam)
        writer.writerow(headers)
        for row in queryset:
            csvrow = [f.encode('utf-8') if isinstance(f, unicode) else f for f in [csv_resolve_field(row, f) for f in fields]]
            writer.writerow(csvrow)
        return response
    
    fields = get_csv_export_field_names(modeladmin)
    
    list_display = []
    for item in modeladmin.list_display:
        if isinstance(item, basestring):
            list_display.append(item)
        else:
            list_display.append(item.__name__)
    
    opts = modeladmin.model._meta
    app_label = opts.app_label
    context = {
        "title": _("Export as CSV"),
        "object_name": force_unicode(opts.verbose_name),
        'queryset': queryset,
        "opts": opts,
        "root_path": modeladmin.admin_site.root_path,
        "app_label": app_label,
        'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
        'fields': fields,
        'list_display': list_display,
    }
    
    # Display the confirmation page
    return render_to_response([
        "admin/%s/%s/csv_export_selected_confirmation.html" % (app_label, opts.object_name.lower()),
        "admin/%s/csv_export_selected_confirmation.html" % app_label,
        "admin/csv_export_selected_confirmation.html"
    ], context, context_instance=template.RequestContext(request))
csv_export_selected.short_description = "Export selection as CSV"