使用Django将生成的CSV文件附加到电子邮件并发送

26

我需要根据查询结果生成一个csv文件,将生成的文件作为附件添加到电子邮件中并发送。正如你所看到的,我需要遍历分配的线索并将其写入文件中,因此我认为yield会起到作用。现在当我运行代码时,我收到了带有以下消息的附件电子邮件,而不是我预期的行。如果我使用return,我将从查询结果中获取一行。

<generator object data at 0x7f5e508d93c0>

def send_lead_reminder(request):
    usercompany = Listing.objects.filter(submitted_by=request.user)
    assigned_leads = lead.objects.filter(assigned_to__in=usercompany).distinct() 
    def data():
        csvfile=StringIO.StringIO()
        csvwriter =csv.writer(csvfile)
        for leads in assigned_leads:
            csvwriter.writerow([leads.business_name, leads.first_name, leads.last_name, leads.email, leads.phone_number,leads.address, leads.city, leads.state, leads.zipcode, leads.submission_date, leads.time_frame, leads.comments])
             yield csvfile.getvalue()
    message = EmailMessage("Hello","Your Leads","myemail@gmail.com",["myemail@gmail.com"])
    message.attach('invoice.csv', data(), 'text/csv')
    #message.to="myemail@gmail.com"
    message.send()
    return HttpResponseRedirect('/')
3个回答

49

你使用额外函数的原因是什么?直接在内存中构建CSV文件 - 如果你要将它附加到电子邮件中,你无法避免这样做 - 然后发送即可。

assigned_leads = lead.objects.filter(assigned_to__in=usercompany).distinct()
csvfile = StringIO.StringIO()
csvwriter = csv.writer(csvfile)
for leads in assigned_leads:
    csvwriter.writerow([leads.business_name, leads.first_name, leads.last_name, leads.email, leads.phone_number,leads.address, leads.city, leads.state, leads.zipcode, leads.submission_date, leads.time_frame, leads.comments])
message = EmailMessage("Hello","Your Leads","myemail@gmail.com",["myemail@gmail.com"])
message.attach('invoice.csv', csvfile.getvalue(), 'text/csv')

很好的答案,只是message.attach的顺序有误。应该是:message.attach('invoice.csv', 'text/csv', csvfile.getvalue())。 - user3167654
@user3167654 - 你确定吗?文档中说:“或者,您可以传递attach()三个参数:文件名、内容和MIME类型。文件名是电子邮件中附件的名称,内容是附件中包含的数据,而MIME类型是附件的可选MIME类型。”文档中给出的示例使用相同的顺序,将MIME类型放在最后。https://docs.djangoproject.com/en/2.1/topics/email/#emailmessage-objects - Peter DeGlopper
是的,你说得对,抱歉。我看错了Flask邮件的顺序。 - user3167654
我也在使用相同的代码,但是我遇到了以下错误。顺便说一下,我正在使用io.StringIO(),因为我正在使用Python 3.6。TypeError: 需要一个类似于字节的对象,而不是'str'。 - Ankit Singh
@AnkitSingh - 我个人没有使用过Python 3的Django,但从那个异常来看,它似乎告诉你发生了什么 - 它期望(编码)字节而不是编码无关的Unicode字符串。csv.writer()期望一个文本模式的文件对象,所以在这里使用StringIO是正确的 - 你需要在附加之前进行编码。我认为csvfile.getvalue().encode(...)应该足够了 - 可能选择utf-8作为你的编码选择,但也可能是其他东西。 - Peter DeGlopper
@PeterDeGlopper 谢谢!昨天我才发现问题出在我用于发送电子邮件的软件包上。我尝试对其进行编码,但问题实际上是软件包本身存在的。不过最终我还是得以继续前进,编辑了软件包并在那里进行了编码。还是谢谢你! - Ankit Singh

8

Python 3和DictWriter示例:

import csv
from io import StringIO
from django.core.mail import EmailMessage

rows = [{'col1': 'value1', 'col2': 'value2'}]
csvfile = StringIO()
fieldnames = list(rows[0].keys())

writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)

email = EmailMessage(
        'Subject',
        'Body',
        'from@email.com',
        ['to@email.com'],
    )
email.attach('file.csv', csvfile.getvalue(), 'text/csv')
email.send()

-2
Neither are working :(

Approach 1:
        msg = EmailMultiAlternatives(subject, body, from_email, [to])
        msg.attach_alternative(file_content, "text/html")
        msg.content_subtype = 'html'
        msg.send()

Approach 2: 
        # email = EmailMessage(
        #     'Report Subject',
        #     "body",
        #     'xx@yy.com',
        #     ['zz@uu.com'],
        #     connection=connection,
        # )
        # email.attach('Report.html', body, 'text/html')
        # email.send()

请在您的解决方案中添加注释/说明。 - buhtz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接