简体   繁体   中英

Django csv export

I have the following csv export function to export model information in csv file. But I am trying to figure out how to show outputs from functions in the model. So the csv export function shows all the fields in the model (fields in the table) but not outputs from functions in the model..

So if I have the following:

def avg_tag(self, obj):
    bids = Bid.objects.active(user=obj.user.id)
    return bids.aggregate(average_price=Avg('list_price'))['average_price']

in the model

It does not get the output from that function.

Here is the csv export function action:

def export_select_fields_csv_action(description="Export selected objects",
                     fields=None, exclude=None, header=True):
def export_as_csv(modeladmin, request, queryset):
    """
    Generic csv export admin action.
    based on http://djangosnippets.org/snippets/1697/
    """
    opts = modeladmin.model._meta
    field_names = [field.name for field in opts.fields]
    labels = []
    if exclude:
        field_names = [v for v in field_names if v not in exclude]
    elif fields:
        field_names = [k for k, v in fields if k in field_names]
        labels = [v for k, v in fields if k in field_names]

    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = ('attachment; filename=%s.csv'
        % unicode(opts).replace('.', '_'))

    writer = csv.writer(response)
    if header:
        if labels:
            writer.writerow(labels)
        else:
            writer.writerow(field_names)
    for obj in queryset:
        writer.writerow([unicode(getattr(obj, field)).encode('utf-8')
            for field in field_names])
    return response
export_as_csv.short_description = description
return export_as_csv

How can I change the function above so that the outputs from functions in the model are outputted in the csv? Thanks!

I guess edit the bit where you loop through the queryset and just add it on the end -

for obj in queryset:
    writer.writerow([unicode(getattr(obj, field)).encode('utf-8')
        for field in field_names] + "," + obj.avg_tag())

You can do something similar to add the heading you want -

if header:
    if labels:
        writer.writerow(labels + "," + "Average Tag")
    else:
        writer.writerow(field_names + "," + "Average Tag"))

UPDATE

It's going to be a bit difficult getting fields and methods because you'll find that there are lots of methods on your model which you didn't define (and you probably don't want in your csv). There's no easy way of differentiating which you want and which you don't.

Have a play with the following to see what's in there -

import inspect
obj = modeladmin.model()
methods = [a for a in dir(modeladmin.model) if inspect.ismethod(getattr(obj, a))]
for method in methods:
    print str(method)

I certainly can't see an elegant way of doing this (or in fact anyway) - I think you're going to have to actually specify each method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM