0

我正在开发一个用 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- 在除第一页之外的每一页的页眉中......为什么它没有显示在第一页上,我怎样才能让它显示在那里?

4

1 回答 1

0

不要传入datetime对象,而是尝试传递它的字符串表示形式:

date_to_display = str(datetime.now())

理想情况下,更好的方法是给文件名加上时间戳(而不是内容),因为这样任何下载的人都可以检查他收到的文件是否是最新的,这可以在不打开文件的情况下完成

为此,只需使用以下命令将时间戳附加到文件名:

filename='temp_%s.pdf' % datetime.now().strftime("%Y%m%d_%H%M%S")
result = open(filename, 'w+b')
于 2016-12-08T15:44:31.887 回答