Django结合Vue实现前端页面导出为PDF2

简介: Django结合Vue实现前端页面导出为PDF


注意:html中需要在head元素中添加<meta charset="UTF-8">,以防生成的pdf中文乱码,另外,确保系统中有中文字体,否则也会出现乱码,如下:

image.png

 

5、 后端接口

仅保留关键代码

#!/usr/bin/env python

# -*- coding:utf-8 -*-

 

__author__ = '授客'

 

from rest_framework.views import APIView

from rest_framework.response import Response

from rest_framework import status

 

from backend.models import SprintTestReport

 

from django.utils import timezone

from django.http import FileResponse

 

 

from django.conf import settings

import pdfkit

import json

import base64

import uuid

import os

import logging

 

logger = logging.getLogger('mylogger')


class SprintTestreportPDFAPIView(APIView):

'''迭代测试报告pdf文件下载'''

 

@staticmethod

def convert_related_plans_to_html(self, related_plans):

'''转换报告相关联的测试计划数据格式为html格式数据,返回转换后的数据'''

 

result = ''

tr = '''<tr>

<td>

<div>{id}</div>

</td>

<td>

<div>{name}</div>

</td>

<td>

<div>{begin_time}</div>

</td>

<td>

<div>{start_time}</div>

</td>

<td>

<div>{end_time}</div>

</td>

<td>

<div>{finish_time}</div>

</td>

<td>

<div>{groups}</div>

</td>

<td>

<div>{environment}</div>

</td>

</tr>'''

 

for related_plan in related_plans:

result += tr.format(**related_plan)

 

return result

 

...略

 

 

 

def post(self, request, format=None):

'''下载pdf格式报告'''

 

result = {}

try:

data = request.data

report_id = data.get('report_id')

 

 

echart_base64_info_dict = data.get('echart_base64_info')

 

# 读取迭代测试报告html模板

report_html_str = '' # 存放html格式的迭代测试报告

 

current_dir, tail = os.path.split(os.path.abspath(__file__))

template_filepath = os.path.normpath(os.path.join(current_dir, 'sprint_test_report/sprint_test_report_template.html'))

with open(template_filepath, 'r', encoding='utf-8') as f:

for line in f:

report_html_str += line

 

# 读取报告数据

sprint_report = SprintTestReport.objects.filter(id=report_id)

if sprint_report.first():

try:

...略

report_data = sprint_report.values('title','introduction', 'related_plans', 'test_scope', 'individual_test_statistics', 'individual_dev_statistics', 'product_test_statistics', 'conclusion', 'suggestion', 'risk_analysis')[0]

 

# 替换测试计划

related_plans = json.loads(report_data['related_plans'])

related_plans = self.convert_related_plans_to_html(related_plans)

report_html_str = report_html_str.replace('${relatedPlans}', related_plans)

 

...略

 

# 生成echart图表图片

time_str = timezone.now().strftime('%Y%m%d')

uuid_time_str = str(uuid.uuid1()).replace('-', '') + time_str

 

file_name_dict = {}

for key, value in echart_base64_info_dict.items():

data_type, base64_data = value.split(',') # value 数据格式 data:image/png;base64,base64编码数据

file_suffix = '.' + data_type.split('/')[1].split(';')[0]

file_name = key + uuid_time_str + file_suffix

file_name_dict[key] = file_name

 

file_path = os.path.normpath(os.path.join(current_dir, 'sprint_test_report/%s' % file_name))

with open(file_path, 'wb') as f:

imgdata = base64.b64decode(base64_data)

f.write(imgdata)

 

# 替换 echart图表

for key in echart_base64_info_dict.keys():

# report_html_str = report_html_str.replace('${%s}' % key, '%s/sprint_test_report/%s' % (current_dir, file_name_dict[key])) # 注意,这里,迭代测试报告模板中的变量名称被设置为和key一样的值,所以可以这么操作

report_html_str = report_html_str.replace('${%s}' % key,os.path.normpath(os.path.join(current_dir, 'sprint_test_report/%s' % file_name_dict[key])))

 

# 生成pdf文档

time_str = timezone.now().strftime('%Y%m%d')

file_name = str(uuid.uuid1()).replace('-', '') + time_str + '.pdf'

config = pdfkit.configuration(wkhtmltopdf=settings.WKHTMLTOPDF)

file_dir = settings.MEDIA_ROOT + '/sprint/testreport'

options = {'dpi': 300, 'image-dpi':600,  'page-size':'A3',  'encoding':'UTF-8', 'page-width':'1903px'}

                   pdfkit.from_string(report_html_str, '%s/%s' % (file_dir, file_name), configuration=config, options=options)                    

file_absolute_path =  '%s/%s' % (file_dir, file_name)

# 删除生成的图片文件

for key in echart_base64_info_dict.keys():

os.remove('%s/sprint_test_report/%s' % (current_dir, file_name_dict[key]))

 

# 返回数据给前端

if os.path.exists(file_absolute_path) and os.path.isfile(file_absolute_path):

file = open(file_absolute_path, 'rb')

file_response = FileResponse(file)

file_response['Content-Type']='application/octet-stream'

file_response['Content-Disposition']='attachment;filename={}.pdf'.format(report_data['title'] ) # 不知道为啥,前端获取不到请求头Content-Disposition

return file_response

else:

result['msg'] = '生成pdf报告失败'

result['success'] = False

return Response(result, status.HTTP_400_BAD_REQUEST)

except Exception as e:

result['msg'] = '%s' % e

result['success'] = False

return Response(result, status.HTTP_500_INTERNAL_SERVER_ERROR)

else:

result['msg'] = '生成迭代测试报告失败,报告不存在'

result['success'] = False

return Response(result, status.HTTP_400_BAD_REQUEST)

except Exception as e:

result['msg'] = '%s' % e

result['success'] = False

return Response(result, status.HTTP_500_INTERNAL_SERVER_ERROR)

 

导出效果(部分截图)

image.png

image.png

image.png

 

目录
相关文章
|
1月前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
1月前
|
前端开发 JavaScript
除了 jsPDF,还有哪些前端库可以用于生成 PDF?
【10月更文挑战第21天】这些前端库都有各自的特点和优势,你可以根据具体的项目需求、技术栈以及对功能的要求来选择合适的库。不同的库在使用方法、性能表现以及功能支持上可能会有所差异,需要根据实际情况进行评估和选择。
|
1月前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
1月前
|
前端开发 API
前端界面生成PDF并导出下载
【10月更文挑战第21天】利用合适的第三方库,你可以在前端轻松实现界面生成 PDF 并导出下载的功能,为用户提供更方便的文档分享和保存方式。你还可以根据具体的需求进一步优化和定制生成的 PDF 文件,以满足不同的业务场景要求。
|
1月前
|
JavaScript 前端开发 搜索推荐
Vue的数据驱动视图与其他前端框架的数据驱动方式有何不同?
总的来说,Vue 的数据驱动视图在诸多方面展现出独特的优势,其与其他前端框架的数据驱动方式的不同之处主要体现在绑定方式、性能表现、触发机制、组件化结合、灵活性、语法表达以及与后端数据交互等方面。这些差异使得 Vue 在前端开发领域具有独特的地位和价值。
|
2月前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
1月前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】 React与Vue:前端框架的巅峰对决与选择策略
|
1月前
|
JavaScript UED
"Vue实战技巧大揭秘:一招解决路由跳转页面不回顶部难题,让你的单页面应用用户体验飙升!"
【10月更文挑战第23天】在Vue单页面应用中,点击路由跳转时,默认情况下页面不会自动滚动到顶部,这可能影响用户体验。本文通过一个新闻网站的案例,介绍了如何使用Vue-router的全局前置守卫和`scrollBehavior`方法,实现路由跳转时页面自动滚动到顶部的功能,提升用户浏览体验。
93 0
|
2月前
|
前端开发 JavaScript API
2025年前端框架是该选vue还是react?有了大模型-例如通义灵码辅助编码,就不用纠结了!vue用的多选react,react用的多选vue
本文比较了Vue和React两大前端框架,从状态管理、数据流、依赖注入、组件管理等方面进行了详细对比。当前版本和下载量数据显示React更为流行,但Vue在国内用户量增长迅速。Vue 3通过组合式API提供了更灵活的状态管理和组件逻辑复用,适合中小型项目;React则更适合大型项目和复杂交互逻辑。文章还给出了选型建议,强调了多框架学习的重要性,认为技术问题已不再是选型的关键,熟悉各框架的最佳实践更为重要。
117 0
|
Web App开发 前端开发 开发工具

热门文章

最新文章