2010-03-18 8 views
7

pdf를 반환하려면이 작은 장고보기를 작성했습니다.Django 및 Reportlab 질문

@login_required 
def code_view(request,myid): 
    try: 
     deal = Deal.objects.get(id=myid) 
    except: 
     raise Http404 
    header = deal.header 
    code = deal.code 
    response = HttpResponse(mimetype='application/pdf') 
    response['Content-Disposition'] = 'attachment; filename=code.pdf' 
    p = canvas.Canvas(response) 
    p.drawString(10, 800, header) 
    p.drawString(10, 700, code) 
    p.showPage() 
    p.save() 
    return response 

그리고 내 질문 :

  • UTF-8 문자가 올바르게 PDF 파일 내에서 표시되지 않습니다.
  • 어떻게 이미지를 포함 할 수 있습니까?

:

  • 어떻게 같은 아주 기본적인 HTML을 포함 할 수 있습니다.

    <ul> 
        <li>List One</li> 
        <li>List Two</li> 
        <li>List Three</li> 
    </ul> 
    
  • 답변

    2

    Reportlab 몇 가지 기본 HTML 서식 (<b>, <i>),이 목록을 할 수 있는지 확실하지 않습니다를 처리 할 수 ​​있습니다. HTML에서 PDF 로의 변환에 pisa을 사용할 수 있습니다. 그런 다음 이미지 포함을 위해 <img> 태그를 사용할 수도 있습니다 (이미지 사용에 PIL을 설치해야합니다)

    10

    다음 레벨로 이동하여 DocTemplates를 사용해야합니다. 이미지는 아주 간단하지만 글 머리 기호를 사용하는 것은 정말 어렵습니다. 스타일 등을 정의해야합니다!

    나는 아래처럼 클래스 세트를 사용

    # -*- coding: utf-8 -*- 
    
    from django.utils.encoding import smart_str 
    from reportlab.lib.colors import Color 
    from reportlab.lib.pagesizes import A4 
    from reportlab.lib.styles import StyleSheet1, ParagraphStyle 
    from reportlab.lib.units import cm 
    from reportlab.pdfgen import canvas 
    from reportlab.platypus.doctemplate import BaseDocTemplate, PageTemplate, \ 
        _doNothing 
    from reportlab.platypus.frames import Frame 
    from reportlab.platypus.paragraph import Paragraph 
    import copy 
    import re 
    from reportlab.platypus.flowables import KeepTogether, Image, PageBreak 
    from htmlentitydefs import name2codepoint 
    from atom.http_core import HttpResponse 
    import tempfile 
    
    def htmlentitydecode(s): 
        return re.sub('&(%s);' % '|'.join(name2codepoint), lambda m: smart_str(unichr(name2codepoint[m.group(1)])), s) 
    
    PS = ParagraphStyle 
    stylesheet = StyleSheet1() 
    
    stylesheet.add(PS(name='Normal', 
            leading=15)) 
    stylesheet.add(PS(name='Bullet', 
            parent=stylesheet['Normal'], 
            bulletFontName = 'Symbol', 
            bulletIndent = 0, 
            bulletFontSize = 13, 
            bulletColor = Color(0.93,0,0), 
            bulletOffsetY = -1.5, 
            leftIndent = 15.8, 
            firstLineIndent = 0, 
           ), alias='bu') 
    stylesheet.add(PS(name='Heading1', 
            parent=stylesheet['Normal'], 
            fontSize=18, 
            spaceAfter=23.5), alias='h1') 
    stylesheet.add(PS(name='Heading2', 
            parent=stylesheet['Normal'], 
            fontSize=14, 
            spaceAfter=4), alias='h2') 
    stylesheet.add(PS(name='Heading3', 
            parent=stylesheet['Normal'], 
            textColor=Color(0.93,0,0) 
           ), alias='h3') 
    stylesheet.add(PS(name='Heading4', 
            parent=stylesheet['Heading3'], 
            textColor='black'), alias='h4') 
    
    BulletStyle = copy.deepcopy(stylesheet["Bullet"]) 
    H1Style = copy.deepcopy(stylesheet["Heading1"]) 
    H2Style = copy.deepcopy(stylesheet["Heading2"]) 
    H3Style = copy.deepcopy(stylesheet["Heading3"]) 
    H4Style = copy.deepcopy(stylesheet["Heading4"]) 
    NormalStyle = copy.deepcopy(stylesheet["Normal"]) 
    
    top_margin = A4[1] - 1.22*cm 
    bottom_margin = 1.5*cm 
    left_margin = 2.8*cm 
    frame_width = 17.02*cm 
    
    right_margin = left_margin + frame_width 
    frame_height = 22.7*cm 
    
    letter_top_margin = 25.0*cm 
    letter_bottom_margin = 3.0*cm 
    letter_left_margin = 2.5*cm 
    letter_right_margin = A4[0] - 2.5*cm 
    letter_frame_width = A4[0] - 5.0*cm 
    letter_frame_height = letter_top_margin - letter_bottom_margin 
    
    
    class LetterTemplate(BaseDocTemplate): 
        _invalidInitArgs = ('pageTemplates',) 
    
        def handle_pageBegin(self): 
         self._handle_pageBegin() 
         self._handle_nextPageTemplate('First') 
    
        def build(self, flowables, onFirstPage=_doNothing, canvasmaker=canvas.Canvas): 
         self._calc() 
    
         frameT = Frame(letter_left_margin, letter_bottom_margin, letter_frame_width, letter_frame_height, 
             leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0, 
             id='normal') 
    
         self.addPageTemplates([PageTemplate(id='First',frames=frameT, onPage=onFirstPage, pagesize=self.pagesize)]) 
    
         if onFirstPage is _doNothing and hasattr(self,'onFirstPage'): 
          self.pageTemplates[0].beforeDrawPage = self.onFirstPage 
    
         BaseDocTemplate.build(self, flowables, canvasmaker=canvasmaker) 
    
    
    class PdfA4Letter(object): 
    
        def __init__(self, filename): 
         self.title = filename 
         self._keep_together = False 
         self.elements = [] 
         self._keep_together_elements = [] 
         self.doc = LetterTemplate(filename,showBoundary=False) 
         self.elements = [] 
    
        def _process_text(self, txt): 
         text_elems = [] 
    
         # avoid us from user added html. 
         txt = txt.replace('&lt;','&lang;').replace('&gt;','&rang;') 
         txt = htmlentitydecode(smart_str(txt).replace('<p>', '').replace('</p>', '<br />')) 
    
         # @todo: in some case the reegxp does not work -> hack 
         txt = txt.replace('target="_blank"', '') 
         # process text 
         for part in re.split('<ul>|</ul>|<ol>|</ol>', txt): 
          part = part.strip() 
          if part.count('<li>') > 0: 
           for item in re.split('<li>|</li>', part): 
            item = item.strip() 
            if len(item) > 0: 
             text_elems.append(Paragraph(item, BulletStyle, bulletText=u'•')) 
          else: 
           text_elems.append(Paragraph(part, NormalStyle)) 
         return text_elems 
    
        def _store_flowable(self, flowable):   
         if self._keep_together == False: 
          self.elements.append(flowable) 
         else: 
          self._keep_together_elements.append(flowable) 
    
        def start_keep_together(self): 
         self.end_keep_together() 
         self._keep_together = True 
    
        def end_keep_together(self): 
         self._keep_together = False 
         if len(self._keep_together_elements) > 0: 
          e = self._keep_together_elements 
          self.elements.append(KeepTogether(e)) 
          self._keep_together_elements = [] 
    
        def newPage(self): 
         self._store_flowable(PageBreak()) 
    
        def blankline(self, cnt=1): 
         self.text(cnt*'<br/>') 
    
        def text(self, txt): 
         for e in self._process_text(txt): 
          self._store_flowable(e)   
    
        def image(self, name, width, height, halign='CENTER'): 
         im = Image(name, width=width, height=height) 
         im.hAlign = halign 
         self._store_flowable(im) 
    
        def h1(self, txt, add_to_toc=True): 
         self.newPage() 
         self._store_flowable(Paragraph(txt, H1Style)) 
    
        def h2(self, txt, add_to_toc=True): 
         self._store_flowable(Paragraph(txt, H2Style)) 
    
        def h3(self, txt, add_to_toc=False): 
         self._store_flowable(Paragraph(txt, H3Style)) 
    
        def h4(self, txt, add_to_toc=False): 
         self._store_flowable(Paragraph(txt, H4Style)) 
    
        def _drawPage(self, canvas, doc): 
         canvas.setSubject('Letter Subject') 
         canvas.setTitle('Letter Title') 
         canvas.setAuthor('Me') 
    
        def build(self): 
         # flush elems 
         self.end_keep_together() 
         self.doc.build(self.elements, self._drawPage) 
    

    당신은 다음과 같이보기에서 PDF 생성을 처리 할 수있는 :

    def view(request): 
    
        file = tempfile.NamedTemporaryFile() 
    
        e = PdfA4Letter(file.name) 
    
        ref = '/absolute/path/to/image.png' 
        e.image(ref, width=frame_width, height=10*cm) 
        e.h1((u'Über Mich')) 
        e.h3('Next header') 
    
        t = """ 
        ascasc<br /> 
        ascascasc<br /> 
        <ul> 
         <li>sdv1</li> 
         <li>sdv2</li> 
         <li>sdv3</li> 
        </ul> 
        ascasc<br /> 
        ascasc<br /> 
        """ 
    
        e.text(t) 
        e.blankline(2) 
        e.end_keep_together() 
        e.build() 
    
        response = HttpResponse(mimetype='application/pdf') 
        response['Content-Disposition'] = 'attachment; filename=gugus.pdf' 
        response.write(file.read()) 
        file.close() 
        return response