如何从模型和模型中创建CSV文件?然后将其添加为电子邮件附件?

时间:2015-04-28 05:14:57

标签: python django email csv

我尝试从存储在我的数据库中的对象生成CSV,然后将csv作为附件添加到电子邮件中。

我正在使用Django 1.7& Python 2.7。

我使用以下代码收到此错误:"属性错误:' _csv.writer'对象没有属性'编码'"

这是我的代码:

def export_as_csv(report, fields, force_fields):
     print "export to csv started"
     """
    Generic csv export admin action.
    based on http://djangosnippets.org/snippets/2020/
    extended for being able to give list_display as fields and work with     admin-defined functions
    """
    opts = report
    if not force_fields:
        field_names = set([field.name for field in opts.fields])
        if fields:
        fieldset = set(fields)
            field_names = field_names & fieldset
    elif fields:
        field_names = set(fields)
    else:
        raise("option force_fields can only be used in parallel with option fields")

    writer = csv.writer(open("myfile.csv","w"), delimiter=',',quoting=csv.QUOTE_ALL)

    writer.writerow(list(field_names))
    row = []
    for field in field_names:
        try:
        row.append(unicode(getattr(report, field)).encode('utf-8'))
        except AttributeError:
            row.append(unicode((getattr(report, field)(report))).encode('utf-8'))
        except:
            raise
    writer.writerow(row)

    response = writer
    return response

下面的代码将上述函数的输出作为mail.attach()中的参数返回。 报告参数是我创建的数据库模型/对象&在调用任何代码之前保存。

list_display = ('primary_id', 'created_date', 'report_size',)
mail = EmailMessage('Email Subject', 'Email Body', None, ['example@example.com'])
mail.attach("report.csv", export_as_csv(report, fields = list_display, force_fields=True) , "text/csv")
mail.send()

这是Report()对象的模型:

class Report(models.Model):
    primary_id = models.IntegerField('Primary Key', primary_key = True, default=0) 
    created_date = models.DateTimeField('Created date', default=timezone.now)
    report_size = models.IntegerField('Report Size', default=0) 

非常感谢任何帮助。

以下是理想情况下我希望此代码如何工作:export_as_csv()返回一个我不需要保存为文件或数据库的CSV对象 - 然后代码将其附加到电子邮件中直接来自内存中的CSV对象,而不是已保存的文件。不确定这是否可行,但这对我的需求是理想的。

1 个答案:

答案 0 :(得分:1)

根据{{​​3}},

csvwriter可以使用write()方法写入任何对象。当您需要内存中的文件类对象时,通常使用的Python类是the docs实例,如果您确定不会向其编写Unicode对象,则使用cStringIO。因此,您的export_to_csv函数应该类似于:

import cStringIO

def export_as_csv(report, fields, force_fields):
    # define field_names as above, assuming your indentation is correct
    csv_buffer = cStringIO.StringIO()        
    writer = csv.writer(csv_buffer, delimiter=',', quoting=csv.QUOTE_ALL)
    field_names = list(field_names) # loses order, but at least it's consistent
    writer.writerow(field_names)
    row = []
    for field in field_names:
        row.append(getattr(report, field).encode('utf-8'))
    writer.writerow(row)
    return csv_buffer

然后像:

mail.attach("report.csv", export_as_csv(report, fields=list_display, force_fields=True).getvalue() , "text/csv")

主要区别是:

1)csv_buffer是一个内存中的文件对象。没有任何内容写入文件系统。

2)这将处理您在示例代码中显示的简单模型字段'primary_id', 'created_date', 'report_size'的字段查找。如果您确实需要处理field_names序列中的可调用名称,则会变得更难。

3)在转换为列表后,它使用单个变量来保存field_names。它可能会使用list(field_names)for field in field_namesfield_names是一个集合,Python集和字典应该是顺序稳定的,只要不做任何修改,但我发现它更清晰,关于确保订单同步更明确更明确。

4)这将返回cStringIO.StringIO对象而不是编写器。一旦你写下你想要的一切,作家的工作就完成了。相反,当您在其上调用cStringIO时,getvalue()对象应返回缓冲的CSV内容。