首页 > 解决方案 > 使用 Django Python 下载带有水印的 PDF 格式的动态 html

问题描述

我正在尝试创建一个测验网络应用程序,用户可以在其中在线或离线进行测验。在离线模式下,用户应该能够单击一个按钮并下载带有图像和水印的 pdf 内容。我的动态 html 内容还包含使用 Mathjx 和 WIRIS 插件打印的数学方程。

我尝试了以下方法,但是

  1. 它的渲染速度超级慢
  2. 我无法在对角线中间打印水印。

我也尝试过使用 jquery/canvas 进行打印,但由于 html 是动态生成的,因此打印不起作用。这可以使用 jquery 和一些 javascript 包来实现吗?

如果可能,请建议一种更快的方法。此外,当我单击 时,下载文件大约需要 15 秒。我想使用 ajax 方法来显示正在进行但无法实现。任何帮助表示赞赏。

class GeneratePdf(View):
    def get(self, request, *args, **kwargs):
            #template = get_template('dashboard/exam-pdf.html')
            quizid = request.GET.get('quizid')
            quiz = Quiz.objects.get(id=quizid)
            questions= #Rendering Questions from model with images and MCQ Options
            print("link clicked")
            context = {
              'questions': questions,
              'essayquestions': essayquestions,
              'quizid':quizid,
              'quiz': quiz
              }
            
                        
            pdf = render_to_pdf('dashboard/exam-pdf.html',context)
         
            #rendering the template
            return HttpResponse(pdf, content_type='application/pdf')

我的考试-pdf.html

{% extends 'base.html' %}
{% load static %}

{% block stylecss %}
 <style>

    @page {
        size: "A4";
        background-image: url('http://127.0.0.1:8000/static/images/watermark.PNG');
        @frame header_frame {           /* Static Frame */
            -pdf-frame-content: header_content;
            left: 30pt; width: 512pt; top: 10pt; height: 30pt;
            
        }
        @frame content_frame {          /* Content Frame */
            left: 30pt; width: 512pt; top: 30pt; height: 632pt;
            background-color: #c48a8a;
        }
        @frame footer_frame {           /* Another static Frame */
            -pdf-frame-content: footer_content;
            left: 30pt; width: 512pt; top: 772pt; height: 20pt;
        } 
        
        
    }
    
 </style>
 {% endblock %}

 {% block content %}
 
 
 <div id="header_content">{{quiz.category.subjectDescr}}
     
 </div>
 <div id="footer_content">Page <pdf:pagenumber>
    of <pdf:pagecount>
</div>


  {% for question in questions %}
     
      <div class="row" >
        <div id="waterMarkContent">
            {%block page_body%}
            <img src="http://127.0.0.1:8000/static/images/watermark.PNG" width="1.5cm">
            {%endblock%}
        </div>
          <div class="col-md-10" >
              <input type=hidden name="question_id" value="{{ question.id }}" class="question_id">
              <div class="panel-heading">                          
                  
                  <p class="panel-title mb-2 mt-2" >
                   
                     <li style="list-style-type: none;" class="mb-1 mt-1"><span style="padding-right:5px;text-decoration:underline">Question #{{forloop.counter}}:</span><strong>  {% autoescape off %}{{ question.content }}{% endautoescape %} </strong></li>
                     <div id="waterMarkContent">
                       
                        <img src="http://127.0.0.1:8000/static/images/watermark.PNG" width="1.5cm">
                        
                    </div>
                   
                      {% if question.figure %}
                      <div class="row mb-1">
                      <img src="{{ question.figure.url }}" alt="{{ question.content }}" />
                      </div> 
                      {% endif %}
                                     
                    {% if question.questionmarks %}
                    <div class="row ml-1" >                      
                       <p style="font-size:0.8rem"><b>Marks :</b>  {{ question.questionmarks }}</p>                      
                    </div>
                    {% endif %}
              </div>
              
              <div class="panel-body ">
              
              <ul >
                      {% regroup question.answer_set.all by get_content_display as answer_list %}
                     
                      {% for answers in answer_list %}
                       <ol>
                        <span>{{ section.grouper }}</span>
                        
                        {% for answer in answers.list %}
                     
                          <li class="list-group-item quiz-answers" >
                              <span><label for="id_answers_0">
                              {{answer.content}}  </label>  </span>
                          </li>  
                        
                        {% endfor %}
                         </ol>
                      {% endfor %}
                  </ul>
            </div>
          </div> 
          
         
      </div>
      <hr>
  {% endfor %}
 

  {% if essayquestions %}
  
  {% for question in essayquestions %}
     
  <div class="row mt-2 mb-4 shadow-1 text-left">
        
          <div class="col-md-10">
              <input type=hidden name="question_id" value="{{ question.id }}" class="question_id">
              <div class="panel-heading">
                 
                  <p class="panel-title mb-1" >
                  
                     <li style="list-style-type: none;"><strong>  {% autoescape off %}{{ question.content }}{% endautoescape %} </strong></li>
  
                     <div class="row mb-1">
                      {% if question.figure %}
                      <img src="{{ question.figure.url }}" alt="{{ question.content }}" />
                      {% endif %}
                    </div>
                    
                    {% if question.questionmarks %}
                    <div class="row mb-1 ml-1" >                       
                       <p style="font-size:0.8rem"><b>Marks :</b>  {{ question.questionmarks }}</p>                      
                    </div>
                    {% endif %}
                
                    </p>
                    <div class="panel-body mb-2">
                        <ul class="list-group mb-2" style="list-style-type: none;">
                            
                            <li class="list-group-item quiz-answers mb-1">
                                <span><textarea name="answers" cols="40" rows="5" style="width:100%" id="answer_{{question.id}}" required>
                                </textarea>  </span>
                            </li>
                            
                        </ul>
                    </div>
               
                
              </div>
              
            </div>
        </div>
        
        <hr>   
    {% endfor %}   

  {% endif %}
</div>
</div>
{% endblock %}
{% block scripts %}

 <script src="https://www.wiris.net/demo/plugins/app/WIRISplugins.js?viewer=image"></script>
 

<script type='text/javascript' async src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML'></script>
<script>

    function tex2img(formula, callback) {
        MathJax.Hub.Queue(function () {
            var wrapper = MathJax.HTML.Element("span", {}, formula);
            MathJax.Hub.Typeset(wrapper, function () {
                var svg = wrapper.getElementsByTagName("svg")[0];
                svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
                var image = new Image();
                image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg.outerHTML)));
                image.onload = function () {
                    var canvas = document.createElement('canvas');
                    canvas.width = image.width;
                    canvas.height = image.height;
                    var context = canvas.getContext('2d');
                    context.drawImage(image, 0, 0);
                    var img = '<img src="' + canvas.toDataURL('image/png') + '"/>';
                    callback(img);
                };
            });
        })
    }

    function render() {
        var dom = document.getElementById("math-tex");
        tex2img(dom.innerText, function (output) {
            dom.innerHTML = output
        });
    }

</script>
<script type="text/javascript">
   function updateMathContent(s) {
       var math = MathJax.Hub.getAllJax("mathdiv")[0];
       MathJax.Hub.Queue(["Text", math, s]);
   }

Array.from(document.querySelectorAll('.watermarked')).forEach(function(el) {
  el.dataset.watermark = (el.dataset.watermark + ' ').repeat(300);
});
</script>


{% endblock %}

实用程序.py

从 io 导入 BytesIO 从 django.http 导入 HttpResponse 从 django.template.loader 导入 get_template

从 xhtml2pdf 导入比萨

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html  = template.render(context_dict)
    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None

标签: pythondjangohtml2pdfxhtml2pdf

解决方案


推荐阅读