Django与reportlab动态报告问题
我正在使用Django和ReportLab工具生成动态PDF报告。报告中的所有数据都来自数据库。
我用ReportLab生成动态PDF报告,这些报告包含数据库中的数据。我的问题是,每当我重启Apache服务器时,PDF报告中的数据就会发生变化。生成的报告使用Django查询来显示数据。但是当我重启Apache服务器后,报告中就不会出现正确的数据。
我检查了我在Django视图中写的所有查询。我还注意到,每次重启Apache服务器时,显示的结果都不同。所以我不认为这是我Django查询的问题。有没有解决这个问题的方法?
如果我重启Apache服务器,已经生成的报告的数据会改变,这个问题的原因是什么,有什么解决方案吗?
或者这和Apache服务器有关吗?
这里是源代码。我觉得StringIO放错地方了。
buffer = StringIO()
def analysis_report(request, sample_no, contact_person):
"""
This function generates the analysis report by using the
client information, transformer details, sample data and
test results of respective analysis.
"""
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment;filename=ANALYSIS_REPORT.pdf'
doc = SimpleDocTemplate(buffer)
document = []
doc.sample_no = sample_no
doc.contact_person = contact_person
image = Paragraph(stamp_image, STYLES['NORMAL_RIGHT'])
document.append(image)
# BUILTIN FUNCTION TO GENERATE THE DOCUMENT.
doc.build(document, onLaterPages=header_footer)
pdf = buffer.getvalue()
response.write(pdf)
return response
提前谢谢你们
1 个回答
3
首先,你的问题可能是因为 buffer = StringIO()
这个代码不在函数的范围内,但你却在函数里使用了它。
我不太确定你具体在做什么——你给我们的代码只是一个完整PDF的最小片段——不过我可以给你一些建议,来自一个刚刚为django项目做了两个很大的PDF包的人:
- 写一个类来创建和封装你的PDF文档对象
- 我写的第一个PDF文档不断扩展,所有逻辑都放在视图里,变得太难管理了
- 你的类应该有一个函数来构建每个页面的模板
- 如果你的页面模板使用了回调
onPage=
,那么每个回调也应该在你的类里单独定义 - 每个独特的数据部分应该有自己的函数(在我的例子里:第一页、第二页和披露部分各自有一个函数,因为它们在逻辑上是不同的数据块)
下面是一个 views.py 的示例:
@check_requirments
def pdf(request) :
"""
Download a PDF
"""
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=new.pdf'
pdf = MyPdf(response)
pdf.add_first_page()
pdf.add_second_page()
pdf.add_disclosures()
pdf.build()
return response
还有我的 Pdf 类的示例:
# Page Setup
PAGE_WIDTH, PAGE_HEIGHT = landscape(letter)
class MyPdf():
"""
My PDF
"""
document = None
def __init__(self, file_like_handle=None):
self.document = BaseDocTemplate(file_like_handle, pagesize=landscape(letter))
self.build_templates()
def build_templates(self):
first_page_frames = []
#First Page Title Frame
frame_title = Frame(.25*inch, PAGE_HEIGHT-(1.75*inch), PAGE_WIDTH-(inch*.5), inch*.5, id="frame_title", showBoundary=0)
first_page_frames.append(frame_title)
# First Page Body Frames
frame_body = Frame(.5*inch, PAGE_HEIGHT-(8*inch), PAGE_WIDTH-(inch), inch*6.25, id="frame_body", showBoundary=0)
first_page_frames.append(frame_body)
# Second Page Body Frame
frame_body_full = Frame(.5*inch, PAGE_HEIGHT-(8*inch), PAGE_WIDTH-(inch), inch*7, id="frame_body_full", showBoundary=0)
templates = []
templates.append(PageTemplate(frames=first_page_frames, id="first_page", onPage=self.first_page))
templates.append(PageTemplate(frames=[frame_body_full], id="child_pages", onPage=self.child_pages))
templates.append(PageTemplate(frames=[frame_body_full], id="child_pages", onPage=self.last_page))
self.document.addPageTemplates(templates)
def first_page(self, canvas, doc):
"""
First page has an image header and footer
"""
canvas.saveState()
canvas.drawInlineImage(settings.MEDIA_ROOT + "../static/pdf-header-landscape.png", inch*.25, PAGE_HEIGHT-(1.25 * inch), PAGE_WIDTH-(.5*inch), ((11/8)*inch))
canvas.drawInlineImage(settings.MEDIA_ROOT + "../static/pdf-footer-landscape.png", inch*.25, inch*.25, PAGE_WIDTH-(.5*inch), (.316*inch))
canvas.restoreState()
def child_pages(self, canvas, doc):
"""
Second page has a smaller header and the same footer
"""
canvas.saveState()
canvas.setFillColor(HexColor("#f4f3f1"))
canvas.rect(inch*.25, PAGE_HEIGHT-(.25 * inch), PAGE_WIDTH-(.5*inch), -(.5*inch), fill=1, stroke=0)
canvas.setFillColor(HexColor("#e5b53b"))
canvas.setFont('Gotham-Bold', 16)
canvas.drawString(inch*.5, PAGE_HEIGHT-((.6)*inch), "PAGE")
canvas.setFillColor(HexColor("#00355f"))
canvas.drawString(inch*1.75, PAGE_HEIGHT-((.6)*inch), "OVERVIEW")
canvas.drawInlineImage(settings.MEDIA_ROOT + "../static/pdf-footer-landscape.png", inch*.25, inch*.25, PAGE_WIDTH-(.5*inch), (.316*inch))
canvas.restoreState()
def build(self):
return self.document.build(self.elements)
def add_first_page(self):
sample = getSampleStyleSheet()
style_title = copy.deepcopy(sample['BodyText'])
style_title.fontSize = 18
style_title.textColor = HexColor("#00355f")
style_body = copy.deepcopy(sample['BodyText'])
style_body.fontSize = 10
style_body.alignment = reportlab.lib.enums.TA_LEFT
style_body.spaceBefore = 25
style_body.spaceAfter = 15
style_body.textColor = HexColor("#000000")
style_body.leading = 14
self.elements.append(Paragraph("""<font color="#e5b53b">PAGE</font>OVERVIEW""", style_title))
self.elements.append(FrameBreak())
self.elements.append(Paragraph("""Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elementum malesuada euismod. Praesent ut ante risus. Aenean eleifend massa elit, non adipiscing ipsum. Integer et arcu tortor, a bibendum metus. Maecenas eget nulla id sem placerat dignissim sit amet et ligula. Donec vitae mi mauris. Praesent lacinia, mauris at malesuada bibendum, metus eros molestie ipsum, sed consequat dolor diam interdum ipsum. Phasellus consectetur auctor laoreet. Suspendisse vel nisl lacus, vitae auctor dui.""", style_body))
# ADD A CUSTOM REPORTLAB CANVAS OBJECT
self.elements.append(SomeGraph())
self.elements.append(Paragraph("""Our strategic allocations for each strategy are determined by our Dynamic Strategic Asset Allocation process - the Science of Dynamic Investing. Our proprietary mathematical model uses updated Price Matters<super>®</super> capital market assumptions (expected return, risk and correlation figures) to determine the optimal allocation to each asset class to achieve the goals of each strategy within the assigned risk tolerance and time horizon. The Art of Dynamic Investing enables us to adapt to changing economic and political realities as we reposition strategies with tactical tilts to the strategic allocations as we see value and momentum of various asset classes being affected during the year. <font color="#e5b53b">The chart below</font> shows the strategic weightings and the tactical allocations to each asset class as of the close of business on the date cited.""", style_body))
self.elements.append(NextPageTemplate("child_pages"))
self.elements.append(PageBreak())
def add_second_page(self):
sample = getSampleStyleSheet()
style_title = copy.deepcopy(sample['BodyText'])
style_title.fontSize = 18
style_title.textColor = HexColor("#00355f")
style_body = copy.deepcopy(sample['BodyText'])
style_body.fontSize = 10
style_body.alignment = reportlab.lib.enums.TA_LEFT
style_body.spaceBefore = 25
style_body.spaceAfter = 15
style_body.textColor = HexColor("#000000")
style_body.leading = 14
self.elements.append(Paragraph("""Morbi posuere erat non nunc faucibus rhoncus. Donec at ante at tellus vehicula gravida. Praesent vulputate viverra neque, ut consectetur turpis vestibulum at. Integer interdum diam sed leo vehicula in viverra mauris venenatis. Morbi tristique pretium nunc vel ultrices. Fusce vitae augue lorem, et feugiat lorem. Donec sit amet nulla eget elit feugiat euismod rutrum ut magna. Pellentesque condimentum, tellus at rutrum egestas, dui neque dapibus risus, malesuada mollis risus eros id ligula. Fusce id cursus nulla. Etiam porttitor vulputate tellus eu blandit. Donec elementum erat sed tellus dapibus eleifend. Pellentesque sagittis, libero ac sodales laoreet, erat turpis fringilla est, vel accumsan nunc nisi eget orci. Integer condimentum libero in tellus lacinia ultricies quis ac odio. Vivamus justo urna, faucibus vitae bibendum dapibus, condimentum et ligula. Nullam interdum velit at orci blandit nec suscipit lorem lobortis. Pellentesque purus nunc, pulvinar vitae ullamcorper id, rhoncus sit amet diam.""", style_body))
def add_disclosures(self):
sample = getSampleStyleSheet()
style_d = copy.deepcopy(sample['BodyText'])
style_d.fontSize = 8
style_d.alignment = reportlab.lib.enums.TA_LEFT
style_d.textColor = HexColor("#9D8D85")
self.elements.append(NextPageTemplate("last_page"))
self.elements.append(PageBreak())
self.elements.append(Paragraph("""Important Disclosures""", style_d))
self.elements.append(Paragraph("""Copyright 2012 Francis Yaconiello All Rights Reserved.""", style_d))
注意:我没有测试这个类,它只是从我已有的类中提取了很多特定应用的信息,并进行了简化,方便理解。这个示例是为了让你了解我如何设置PDF的最佳实践。