[Django]templateをpdfに変換してメールを送り、結果も!

4518 ワード

DjangoテンプレートをPDF形式に変換し、電子メールに添付して結果を保存する機能を実現します.

weasyprint


pythonのweasyprintライブラリを使用してテンプレートをpdfに変換します.
📂 WeasyPrint Document
def send_email(email, *args):
    requestDate = str(datetime.datetime.now())[:10]
    task = _send_email.delay(email, requestDate, *args)
    

@app.task
def _send_email(email, requestDate, *args):
    ctx = {
        "date": requestDate,
        "data": your_data
    }

    html_string = render_to_string(YOUR_EMAIL_TEMPLATE, ctx)
    html = HTML(string=html_string)
    buffer = io.BytesIO()
    html.write_pdf(target=buffer)
    pdf = buffer.getvalue()

    email_message = EmailMultiAlternatives(
        to=(email,),
        subject="메일 제목",
        body="""
        메일 내용
        """,
    )
    filename = 'pdf파일 제목.pdf'
    mimetype_pdf = 'application/pdf'
    email_message.attach(filename, pdf, mimetype_pdf)
    email_message.send(fail_silently=False)

メッセージ送信結果の取得


方法1)セロリを利用した結果


下図に示すように、AsyncResultを使用するとセロリの結果が得られます.セロリの結果については以前ブログでも確認できました!
📂 Celery results Document
from celery.result import AsyncResult


def send_email	
    task = _send_email.delay(email, tmpdata)
    response = AsyncResult(str(task))
    state = response.state
    
そうすると、PENDINGとしか表示されないホットスポットが続き、セロリdocsとstackoverflowを探しましたが、役に立ちませんでした.
それ以外に、CELERY_ALWAYS_EAGER = Trueまたは.delay().run()に変換する動作は、非同期を使用しない方法であるため除外される.
だから探して探してた...

方法2)django email結果の使用


ドラムなら.
The return value will be the number of successfully delivered messages (which can be 0 or 1 since it can only send one message).
正常に送信されたメールの数を返すことで、成功は1を返し、失敗は0を返します!こつこつ!最後に、email sendの応答をdbに保存します.

最終コード

from weasyprint import HTML

from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string


def send_email(email, *args):
    requestDate = str(datetime.datetime.now())[:10]
    task = _send_email.delay(email, requestDate, *args)
    

@app.task
def _send_email(email, requestDate, *args):
    ctx = {
        "date": requestDate,
        "data": your_data
    }

    html_string = render_to_string(YOUR_EMAIL_TEMPLATE, ctx)
    html = HTML(string=html_string)
    buffer = io.BytesIO()
    html.write_pdf(target=buffer)
    pdf = buffer.getvalue()

    email_message = EmailMultiAlternatives(
        to=(email,),
        subject="메일 제목",
        body="""
        메일 내용
        """,
    )
    filename = 'pdf파일 제목.pdf'
    mimetype_pdf = 'application/pdf'
    email_message.attach(filename, pdf, mimetype_pdf)
    response = email_message.send(fail_silently=False)
    qs = Emailresult.objects.get(id=id)
    if response == 1:
        qs.send_status = "complete" 
        qs.completed = datetime.datetime.now()
    else:
        qs.send_status = "fail"
    qs.save()

この過程で出会った問題は...


pdfを変換する時韓国語は蒸し煮ません


Unicodeは以下のように復号されていないため、ハングルでは表示できないという問題が発生した.

検索ブログはweasyprintがcairo(グラフィックライブラリ)とpango(fontライブラリ)に依存していることを発見し、pangoはローカルフォントを使用しているため、pcにfontをインストールする必要がある.

Worker container


メールは非同期処理なのでworkerが使用されますが、ここでworker docker containerは自動的に反映されません.したがって,コード修正が発生した場合はコンテナの再生成を継続すべきであるが,そうはしないため,コードが誤りであると判断し,修正と修正を繰り返す.最初からworker containerを再生成すればいい.