django - 通过模板使用 django 管理 pdf 并作为电子邮件附件发送

标签 django python-3.x django-templates xhtml2pdf

我正在使用 django 框架创建一个学生注册网站。

我已经到达一个地方,我必须向用户显示表格,并且我收到处理后输入的信息,我必须向用户发送一封电子邮件,其中包含他输入的信息,将其放入 PDF 中我必须从包含上下文字典的模板生成。

目前我可以生成的 PDF 只能通过函数 HttpResponse 将其发送到浏览器,但问题是用户决定下载它或不是,我更有可能 Handlebars 放在 pdf 上,将其作为附件发送。

我想打开一个数据库,其中有一个models.FileField类型的字段,通过我可以保存的库xhtml2pdf生成带有上下文字典的pdf用信号在数据库中,然后以文件作为附件发送电子邮件。

目前我尝试实现此目的的方法都没有成功。这是我的代码:

utils.py

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

模型.py

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

最佳答案

我的代码你有这部分:

def send_mail_insciption(instance):
    ...
    email_pdf.attach_alternative(instance.pdf, "application/pdf")
    email_pdf.send()

错误消息(和回溯)表明电子邮件需要字节作为附件,但 instance.pdfFieldFile .

尝试将文件转换为字节,也许使用 instance.pdf.read() 并让我们知道这是否可以解决问题。

关于django - 通过模板使用 django 管理 pdf 并作为电子邮件附件发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49991490/

相关文章:

python - python项目中的Elasticsearch

Django 管理更改列表顶部和底部的滚动条

python - PDF、Django、二维码、reportlab

django - request.method == "POST"在 Django 中意味着什么?

python - 在 python 包中使用另一个文件中的类并在 __init__() 中发生冲突

python - 使用正则表达式仅打印字符串中的字母

javascript - Django:在 Google map 的 javascript 中使用模板标签

python - 在 PIL 中更改图像的对比度

python - Django - 显示图像和图像链接

python - 如何在模板中呈现外键字段?