我正在开发一个用 Python/Django 编写的项目,特别是想对其其中一个功能进行小幅改动。
在其中一个网页上,有一个按钮,单击该按钮将生成一个 PDF 文档,其中包含有关数据库中项目的信息。
我只是想在 PDF 中添加一个“日期”,这样每当单击按钮并生成 PDF 时,就会生成它,并在标题中显示今天的日期,以跟踪创建哪个 PDF 的时间(因为每次用户生成它们时它们可能会显示不同的信息)。
显示按钮的页面的 URL 是:www.xyz.com/costing/5915/
URL '/5915/' 中的数字是用户当前正在使用的项目的 ID。在costing
应用程序的 urls.py 文件中,有以下行:
url(r'^(?P<project_id>[0-9]+)/$', views.costing_home, name='home'),
这view
是在views.py中定义的:
def costing_home(request, project_id):
""" Current costing home page in FileMaker with budget reports, CCIs, variations etc """
project = Project.objects.get(id=project_id)
context = {'project': project, 'mini_form':CostingMiniForm(instance=project)}
if project.budget_overview.deposit_budget_saved:
curr_budget = Budget.objects.get_or_create(project=project, version_number=None, current_marker=False)[0]
context['current_budget'] = curr_budget
return render(request, 'costing/costing_post_deposit.html', context)
else:
curr_budget = get_current_budget(project_id) or Budget.objects.get_or_create(project=project, version_number=None, current_marker=False)[0]
context['current_budget'] = curr_budget
versions = project.budget_versions.annotate(item_count=Count('budget_items')).filter(version_number__gte=0,)
saved_versions = versions.filter(item_count__gt=0)
presentations = versions.filter(item_count=0)
if saved_versions: context['version_formset'] = VersionFormSet(queryset=saved_versions)
if presentations: context['presentations'] = presentations
print curr_budget
return render(request, 'costing/costing_pre_deposit.html', context)
我知道我想要添加日期的是“post_deposit”项目(即“5915”是“post_deposit”项目的 ID)
如果我转到 Sublime 中的 costing/costing_post_deposit.html 文件,我可以看到它具有以下结构:
{% block costing %}
...
{% endblock costing %}
{% block reports %}
<div class="app-wrap clear">
...
<div class="app sm {{app.color}}">
<a class="filler" id="pdf2_package" data-view-url="{% url 'costing:pdf2_master' project.id %}"></ a>
<strong>Save pdf payment package</strong>
<a id="new_payment_pdf" class="hidden" href="" target="_blank"></a>
</div>
</div>
{% endblock reports %}
...
带有文本“保存 pdf 付款包”的类是我按下以生成 PDF 的按钮(单击该按钮还会打开一个“新电子邮件”,并附上生成的 PDF,以便将其发送到客户)
据我了解,传递给data-view-url
此类的视图(即costing:pdf2_master
)是用于生成 PDF 的视图。此视图定义为:
def pdf2_master(request, project_id):
project = Project.objects.select_related('budget_overview').prefetch_related('budget_versions', 'payments').get(id=project_id)
""" Save to the current budget (no version number), as versions not used once deposit is received """
budget = get_current_budget(project_id)
# Create a date variable to displays today's date on the PDF when it's generated
date_to_display = datetime.now()
if not budget:
Budget.objects.create(project=project, current_marker=1)
project.payments.first().recalc_balance_payment()
""" Payments """
future = datetime.now()+timedelta(days=9999)
payments = list(project.payments.exclude(is_balance_payment=True).annotate(date_null=Coalesce('date_due', Value(future))).order_by('date_null', 'date_due', 'number'))
try: payments.append(project.payments.get(is_balance_payment=True)) #Ensure balance payment is the last in the list
except ObjectDoesNotExist: pass
def get_payment_details(payment):
payment_amount_exc = payment.amount_exc_vat
payment_amount_inc = inc_vat(payment.amount_exc_vat, project.vat_status)
vat = payment.amount_inc_vat - payment.amount_exc_vat
if payment.requested and not payment.date_paid:
status = 'due'
elif payment.requested and payment.date_paid:
status = 'paid'
else:
status = 'hidden'
return [
['Payment', payment.name],
['Date', payment.date_due],
['Scheduled payment (£)', payment_amount_exc],
['VAT (£)', vat],
['Gross payment (£)', payment_amount_inc, status],
['Date paid', payment.date_paid],
]
payments_details = [get_payment_details(p) for p in payments]
budget_overview = project.budget_overview
payment_made = budget_overview.total_paid_exc
budget_exc_vat = budget_overview.updated_exc_vat
outstanding = budget_overview.outstanding_exc
outstanding_inc = budget_overview.outstanding_inc
net_payment_due = budget_overview.net_payment_due
gross_payment_due = inc_vat(net_payment_due, project.vat_status)
""" Post deposit budget overview styled for pdf """
try:
construction_variations = project.variations.total_construction
client_variations = project.variations.total_client
except ObjectDoesNotExist:
construction_variations = 0
client_variations = 0
grouped_totals = [
['Construction budget', budget.item_total_exc_vat() or 0],
['Construction variations', construction_variations],
['Client variations', client_variations],
['Client choice items', budget.cci_total_exc_vat_final],
]
total_exc = project.budget_overview.updated_exc_vat
total_inc = project.budget_overview.updated_inc_vat
""" CCIs """
cci_grouped_items = budget.cci_items.all().order_by('project_room', 'room', 'name')
""" Agreed client & construction variations """
try:
variations = project.variations.addomit_set.filter(date_agreed__isnull=False).order_by('item__project_room', 'item__room', '-date_agreed').annotate(sca=Case(When(item__notes__icontains='standard cost assumption', then=Value(1)), output_field=IntegerField()) )
# variations.filter(item__notes__icontains='standard cost assumption')
agreed_total = sum([i.item.total_inc_profit for i in variations])
client_variations = variations.filter(variation_type=1).order_by('-date_agreed')
client_agreed_total = sum([i.item.total_inc_profit for i in client_variations])
construction_variations = variations.filter(variation_type=1).order_by('-date_agreed')
construction_agreed_total = sum([i.item.total_inc_profit for i in construction_variations])
unagreed_variations = project.variations.addomit_set.filter(date_agreed__isnull=True, item_reported__isnull=False).order_by('item__project_room', 'item__room', '-date_agreed')
except ObjectDoesNotExist:
variations = ''
agreed_total = ''
client_variations = ''
client_agreed_total = ''
construction_variations = ''
construction_agreed_total = ''
unagreed_variations = ''
pdf_context = {
'project': project,
'date_to_display': date_to_display,
'budget': budget,
'grouped_totals': grouped_totals,
'total_exc': total_exc,
'total_inc': total_inc,
'cci_grouped_items': cci_grouped_items,
'cci_total_exc': budget.cci_total_exc_vat_final,
'variations': variations,
'agreed_total_exc': agreed_total,
'client_variations': client_variations,
'client_agreed_total_exc': client_agreed_total,
'construction_variations': construction_variations,
'construction_agreed_total_exc': construction_agreed_total,
# 'grouped_unagreed_variations': grouped_unagreed_variations,
'unagreed_variations': unagreed_variations,
'payments_details': payments_details,
'latest_total_exc': budget_exc_vat,
'total_paid_exc': payment_made,
'outstanding_exc': outstanding,
'outstanding_inc': outstanding_inc,
'net_payment_due': net_payment_due,
'gross_payment_due': gross_payment_due,
}
template = get_template('pdf2_base.html')
html = template.render(pdf_context)
filename='temp.pdf'
result = open(filename, 'w+b')
pdf = pisa.pisaDocument(src=StringIO.StringIO(
html.encode("UTF-8")), link_callback=fetch_resources, dest=result)
file_to_be_saved = result
if request.GET.get('quick-pdf'):
temp_pdf_obj = Spreadsheet.objects.get_or_create(id=2)[0]
temp_pdf_obj.file.save('temp.pdf', File(file_to_be_saved))
result.close()
file_path = temp_pdf_obj.file.file.name
return open_pdf(file_path)
# Change to save on payment without PDF
payment = project.payments.filter(date_paid__isnull=True, requested=True).order_by('number').last()
if not payment:
payment = project.payments.get(is_balance_payment=True)
# print 'Saving to payment ', payment.number
payment_pdf = payment.pdf_package
payment_pdf.save('{}/Client Payments/{} {} Payment.pdf'.format(CCD, FDS, project.project_code.upper()), File(file_to_be_saved))
result.close()
""" Presentation meeting report. Variables key: Subject: {0: Project name, 1: date DD.MM.YY} Body: {0: Email template,} """
template = EmailTemplate.objects.get(code=10)
email_to = template.get_email_addresses(project_id)
# Make variables for subject/body
date_str = datetime.now().strftime('%d.%m.%Y')
subject = template.subject.format(project.project_name, date_str)
body = template.body([payment.email_content])
file = payment_pdf.file
filename = file.name.split('/')[-1]
mailto = 'mailto:{}?subject={}&body={}&cc={}'.format(email_to, subject, '%0D%0A'.join(body.split('\n')), accounts_email)
pdf_url = reverse('costing:pdf_open', args=[payment.id])+"?pdf=payments"
return JsonResponse({'success':'Made pdf version', 'mailto': mailto, 'pdf_url': pdf_url})
我尝试date_to_display
在视图中添加一个变量,并将其设置为datetime.now()
, 以获取当前日期,然后将该变量添加到pdf_context
以下行:
'date_to_display': date_to_display,
但是,当我单击该 URL 上的“保存 PDF 付款包”按钮时,虽然生成了 PDF,但当我打开它时,我无法在任何地方看到我添加到其中的日期......这是为什么? 创建 PDF 时如何将今天的日期添加到 PDF 中?
编辑
实际上,我认为问题可能在于,如果今天已经生成了 PDF,那么新的 PDF 不会保存 - 当我查看已生成的 PDF 时,它说它是在几个小时前最后修改的,即使我在 5 分钟前按下了“保存 PDF 付款包”按钮。
如何检查我正在生成的 PDF 是否已经存在,如果存在,则重命名我正在生成的 PDF,以包含当前日期/时间,以便它具有唯一的文件名?
此外,似乎今天的日期被添加到 PDF- 在除第一页之外的每一页的页眉中......为什么它没有显示在第一页上,我怎样才能让它显示在那里?