django - 如何在 Django 项目中将请求传递给 Celery 任务参数?
问题描述
我正在使用wkhtmltopdf
Django 生成 PDF 文件并将其通过电子邮件发送给某人。这是我的看法:
class ChallanEmail(AtomicMixin, View, LoginRequiredMixin):
template = "europarts/challan/email_template.html"
def get(self, request, **kwargs):
challan = Challan.objects.get(pk=kwargs['pk'])
ref_no = challan.ref_no
date = challan.created
recipient = challan.recipient
address = challan.recipient_address
challan_rows = ChallanRow.objects.filter(challan=challan)
context = {
"ref_no": ref_no,
"date": date,
"recipient": recipient,
"address": address,
"challan_rows": challan_rows,
}
response = PDFTemplateResponse(
request=request,
template=self.template,
filename='challan_email.pdf',
context=context,
show_content_in_browser=True,
cmd_options={'margin-top': 10,
'zoom': 1,
'viewport-size': '1366 x 513',
'javascript-delay': 1000,
'no-stop-slow-scripts': True},
)
file_path = os.path.join(settings.BASE_DIR, settings.MEDIA_ROOT, 'challan_email.pdf')
with open(file_path, 'wb') as f:
f.write(response.rendered_content)
subject = 'From Design Ace Limited'
body = self.request.GET.get('email_body', '')
from_email = 'Sorower Hossain <sorower@europartsbd.com>'
to = ['{}'.format(self.request.GET.get('to_address'))]
attachment = os.path.join(settings.MEDIA_ROOT, 'challan_email.pdf')
send_email(subject, body, from_email, to, attachment)
return HttpResponseRedirect(reverse('europarts:challan_details', args=(kwargs['pk'],)))
正如您在最后看到的那样,我正在发送带有任务 ( send_email
) 的电子邮件,使用celery
. 但是,最耗时的过程是 PDF 创建过程。这是执行此操作的代码部分:
response = PDFTemplateResponse(
request=request,
template=self.template,
filename='challan_email.pdf',
context=context,
show_content_in_browser=True,
cmd_options={'margin-top': 10,
'zoom': 1,
'viewport-size': '1366 x 513',
'javascript-delay': 1000,
'no-stop-slow-scripts': True},
)
我面临的问题是,每当我尝试将所有参数传输到 celery 任务时,它都会显示错误,因为request
它不可序列化。如何将请求转移到我的 celery 任务并节省 PDF 生成时间?这项任务几乎需要三秒钟,这非常多。
解决方案
如果您PDFTemplateResponse
仅用于生成 pdf 文件并通过电子邮件发送(而不是作为 http 响应),则可以在 celery 任务中模拟它。
您的芹菜任务,在<app_name>/tasks.py
文件中:
from django.test.client import RequestFactory
# other necessary imports
...
@shared_task
def create_pdf_and_send_email(template, context, email_body, to_address):
request = RequestFactory().get('') # any valid url
challan_rows = ChallanRow.objects.filter(pk__in=context['challan_rows'])
context['challan_rows'] = challan_rows
response = PDFTemplateResponse(
request=request,
template=template,
filename='challan_email.pdf',
context=context,
show_content_in_browser=True,
cmd_options={'margin-top': 10,
'zoom': 1,
'viewport-size': '1366 x 513',
'javascript-delay': 1000,
'no-stop-slow-scripts': True},
)
file_path = os.path.join(settings.BASE_DIR, settings.MEDIA_ROOT, 'challan_email.pdf')
with open(file_path, 'wb') as f:
f.write(response.rendered_content)
subject = 'From Design Ace Limited'
body = email_body
from_email = 'Sorower Hossain <sorower@europartsbd.com>'
to = ['{}'.format(to_address)]
attachment = os.path.join(settings.MEDIA_ROOT, 'challan_email.pdf')
send_email(subject, body, from_email, to, attachment)
而你的重构get
方法:
from .tasks import create_pdf_and_send_email
...
def get(self, request, **kwargs):
challan = Challan.objects.get(pk=kwargs['pk'])
ref_no = challan.ref_no
date = challan.created
recipient = challan.recipient
address = challan.recipient_address
challan_rows = ChallanRow.objects.filter(challan=challan).values_list('pk', flat=True)
context = {
"ref_no": ref_no,
"date": date,
"recipient": recipient,
"address": address,
"challan_rows": challan_rows,
}
email_body = self.request.GET.get('email_body', '')
to_address = self.request.GET.get('to_address')
create_pdf_and_send_email.delay(template, context, email_body, to_address)
return HttpResponseRedirect(reverse('europarts:challan_details', args=(kwargs['pk'],)))
我希望它应该有效。
如果序列化错误有任何问题(可能与变量中的address
字段有关),请更改为in方法。然后,在 celery 任务中,使用给定的 pk 检索地址(例如,并替换为.context
address = challan.recipient_address
address = challan.recipient_address.pk
get
address = YourAddressModel.objects.get(pk=context['address'])
context['address']
context['address'] = address
推荐阅读
- sql-server - 选择基于特定行的简单规则
- python - python:opencv比较直方图结果
- java - veraPDF PDF/A 验证 java.lang.NoSuchMethodError: org.apache.fontbox.ttf.TrueTypeCollection.getFonts()Ljava/util/List
- c# - Xamarin 中特定于平台的返回类型
- vb.net - 是否有一种语法简洁的方法可以从 vb 中的对象列表中提取参数列表
- sql - 如何为此代码使用按功能分组
- puppeteer - elementHandle.$$(selector) 返回字符串而不是 elementHandles
- assembly - ARM v8 中的 LDUR 和 STUR
- json - Gson JSON 输出在转换后的字段名称中包含空格
- c - 将项目添加到数据结构 (C)