Magic with Python, getattr and eval

We have a Django project with the admin module to manage our models, some of them have an action to export model objects as CSV.

What if we want to generate a report and attach it to an email to send it once a week? Easy with Python and Django! :-)


from django.core.management import setup_environ
import os
import sys
path = os.path.dirname(__file__).replace("cron", "")
if not path in sys.path:
    sys.path.append(path)

In my case the script has to be executed outside django itself, that lines add scripts path ("cron") into python path and keeps django project environment available to access to its classes.


user = User.objects.all()[0]
report_list = ['Account', 'Order', 'Invoice']
request = HttpRequest()
request.user = user

email = EmailMessage('My report', 'Hi you! heres your report', [email protected]',
            [[email protected]', [email protected]'])

for report in report_list:
    model = eval(report)
    modeladmin = eval(report + "Admin")

    o = modeladmin(model, "")
    report_data = getattr(modeladmin, 'export_as_csv')(o, request, model.objects.all())
    email.attach("%ss.csv" % report.lower(), report_data, 'text/csv')

email.send()

I like to follow conventions, if you do you'll be grateful later like me. In this example we have some models ('Account', 'Order', 'Invoice') and its Admin classes ('AccountAdmin', 'OrderAdmin', 'InvoiceAdmin'), inside them an "export_as_csv" method which it's used to generate our report.

We can also use elements of the list to access models with eval(string), evaluating the string as a Python expression, so we get the class name of the Model and the ModelAdmin.

Finally we get the corresponding method of different Admin models passing a HttpRequest, and a User object (we need that in our example) to emulate the original export_as_csv admin method.

Then we can attach all files to the email and send it. :-)

Javier Aguirre

Read more posts by this author.

comments powered by Disqus