[Django] template을 pdf로 변환 후 메일전송, 결과까지!
Django template를 PDF형식으로 변환하고 이메일에 첨부하여 발송하고 그 결과를 저장하는 기능을 구현해보자..
weasyprint
python의 weasyprint 라이브러리를 이용해 template를 pdf로 변환을 해준다.
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) celery 결과 이용
아래와 같이 AsyncResult를 이용하면 celery의 결과를 가져올 수 있다. celery 결과에 대한 내용은 예전 블로그에서도 확인 할 수 있다!
from celery.result import AsyncResult
def send_email
task = _send_email.delay(email, tmpdata)
response = AsyncResult(str(task))
state = response.state
이렇게 진행하니 결과가 계속해서 PENDING
으로만 뜨는 이슈가 발생해서 celery 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의 response를 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는 local에 있는 폰트를 사용하기 때문에 pc에 font를 설치해줘야 한다고 한다.
Worker container
메일을 비동기로 처리하다보니 worker를 이용하게되느데 여기서 worker docker container는 자동 반영이 아니다. 그래서 코드 수정사항 발생시 계속 컨테이너를 재 생성했어야하는데 그러지 않아서 코드가 잘못된줄알고 수정과 수정반복.. 그냥 처음부터 worker container를 재 생성해주면 됐다..
Author And Source
이 문제에 관하여([Django] template을 pdf로 변환 후 메일전송, 결과까지!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@anjaekk/Django-template을-pdf로-변환-후-메일전송-결과까지저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)