我正在使用django框架为学生注册创建一个网站。
我到达了一个我必须向用户显示表格的地方,我收到了治疗后输入的信息我必须通过将他们放入PDF格式向用户用户发送包含他输入的信息的电子邮件。我必须从包含上下文字典的模板生成。
目前我可以生成的PDF只能通过函数HttpResponse
发送到浏览器,但问题是用户决定是否下载它而我有更多的可能把手放在pdf上作为附件发送。
我想打开一个数据库,其中会有一个models.FileField
类型的字段,通过库xhtml2pdf
生成带有上下文字典的pdf,我可以用信号保存在数据库中然后通过将文件作为附件发送电子邮件。
我试图实现这一目标的方法目前都没有成功。这是我的代码:
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type="application/pdf")
return None
from django.conf import settings
from django.db.models.signals import pre_save, post_save
from django.core.mail import EmailMessage, EmailMultiAlternatives
from django.db import models
# Create your models here.
class MyModel(models.Model):
order_id = models.CharField(max_length=255)
nom = models.CharField(max_length=255)
email = models.EmailField()
pdf = models.FileField(upload_to="pdfs", null=True, blank=True)
def create_order_id(instance, new_order_id=None):
order_id = instance.id
if new_order_id is not None:
order_id = new_order_id
qs = MyModel.objects.filter(order_id=order_id)
exists = qs.exists()
if exists:
new_order_id = "%s-%s" %(order_id.first().id)
return create_order_id(instance, new_order_id)
return order_id
def pre_save_receiver(sender, instance, *args, **kwargs):
if not instance.order_id :
instance.new_order_id = create_order_id(instance)
def send_mail_insciption(instance):
subject = "Thank you"
from_email = settings.EMAIL_HOST_USER
to_email = [instance.email]
body = "Votre inscription"
email_pdf = EmailMultiAlternatives(
subject = subject,
body =body,
from_email = from_email,
to=to_email,
)
email_pdf.attach_alternative(instance.pdf, "application/pdf")
email_pdf.send()
def post_save_receiver(sender, instance, *args, **kwargs):
send_mail_insciption(instance)
pre_save.connect(pre_save_receiver, sender=MyModel )
post_save.connect(post_save_receiver, sender=MyModel)
#views.py
def pdf_genarete(request):
form = MyModelForm(request.POST or None)
if form.is_valid():
nom = form.cleaned_data.get("nom")
email = form.cleaned_data.get("email")
obj = MyModel.objects.create(nom=nom, email=email)
context = {"models_instance": obj}
pdf = render_to_pdf("pdfapp/template_pdf.html", context)
filename = "mypdf_{}.pdf".format(obj.order_id)
pdf.save()
obj.pdf.save(filename, File(BytesIO(pdf.content)))
return redirect(reverse("home"))
return render(request, "pdfapp/formulaire.html", {"form": form})
执行此处后,终端上出现错误:
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/db/models/base.py", line 769, in save_base
update_fields=update_fields, raw=raw, using=using,
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 178, in send
for receiver in self._live_receivers(sender)
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 178, in <listcomp>
for receiver in self._live_receivers(sender)
File "/home/michel/saintexupery/saintexupry/pdfapp/models.py", line 69, in post_save_receiver
send_mail_insciption(instance)
File "/home/michel/saintexupery/saintexupry/pdfapp/models.py", line 65, in send_mail_insciption
email_pdf.send()
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/message.py", line 294, in send
return self.get_connection(fail_silently).send_messages([self])
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/backends/smtp.py", line 110, in send_messages
sent = self._send(message)
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/backends/smtp.py", line 124, in _send
message = email_message.message()
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/message.py", line 254, in message
msg = self._create_message(msg)
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/message.py", line 440, in _create_message
return self._create_attachments(self._create_alternatives(msg))
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/message.py", line 450, in _create_alternatives
msg.attach(self._create_mime_attachment(*alternative))
File "/home/michel/saintexupery/env/lib/python3.6/site-packages/django/core/mail/message.py", line 393, in _create_mime_attachment
Encoders.encode_base64(attachment)
File "/usr/lib/python3.6/email/encoders.py", line 32, in encode_base64
encdata = str(_bencode(orig), 'ascii')
File "/home/michel/saintexupery/env/lib/python3.6/base64.py", line 534, in encodebytes
_input_type_check(s)
File "/home/michel/saintexupery/env/lib/python3.6/base64.py", line 520, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not FieldFile
答案 0 :(得分:0)
我的代码你有这个部分:
def send_mail_insciption(instance):
...
email_pdf.attach_alternative(instance.pdf, "application/pdf")
email_pdf.send()
错误消息(和追溯)表示电子邮件需要字节作为附件,但instance.pdf
是FieldFile
。
尝试将文件转换为字节,也许使用instance.pdf.read()
并告诉我们是否能解决问题。