{"id":20488,"date":"2025-05-29T07:16:52","date_gmt":"2025-05-29T07:16:52","guid":{"rendered":"https:\/\/techpearl.com\/1719395789229\/?p=20488"},"modified":"2025-06-03T03:55:15","modified_gmt":"2025-06-03T03:55:15","slug":"creating-pdf-and-converting-to-pdf-a-using-python-and-ghostscript","status":"publish","type":"post","link":"https:\/\/techpearl.com\/1719395789229\/creating-pdf-and-converting-to-pdf-a-using-python-and-ghostscript\/","title":{"rendered":"Creating PDF and Converting to PDF\/A using Python and Ghostscript"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"20488\" class=\"elementor elementor-20488\" data-elementor-settings=\"[]\">\n\t\t\t\t\t\t\t<div class=\"elementor-section-wrap\">\n\t\t\t\t\t\t\t<section class=\"has_ma_el_bg_slider elementor-section elementor-top-section elementor-element elementor-element-2cd63f20 elementor-section-boxed elementor-section-height-default elementor-section-height-default jltma-glass-effect-no\" data-id=\"2cd63f20\" data-element_type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"has_ma_el_bg_slider elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-437687b9 jltma-glass-effect-no\" data-id=\"437687b9\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6fd6e2d4 jltma-glass-effect-no elementor-widget elementor-widget-theme-post-title elementor-page-title elementor-widget-heading\" data-id=\"6fd6e2d4\" data-element_type=\"widget\" data-widget_type=\"theme-post-title.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Creating PDF and Converting to PDF\/A using Python and Ghostscript<\/h1>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-654a0e5 elementor-author-box--align-left elementor-author-box--image-valign-top jltma-glass-effect-no elementor-widget elementor-widget-author-box\" data-id=\"654a0e5\" data-element_type=\"widget\" data-widget_type=\"author-box.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-author-box\">\n\t\t\t\n\t\t\t<div class=\"elementor-author-box__text\">\n\t\t\t\t\t\t\t\t\t<div >\n\t\t\t\t\t\t<h4 class=\"elementor-author-box__name\">Vinod Charan Kumar<\/h4>\t\t\t\t\t<\/div>\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-49769c6d bdt-ss-btns-view-icon bdt-ss-btns-shape-rounded bdt-ss-btns-align-left bdt-ep-grid-0 bdt-ss-btns-style-flat bdt-ss-btns-color-original jltma-glass-effect-no elementor-widget elementor-widget-bdt-social-share\" data-id=\"49769c6d\" data-element_type=\"widget\" data-widget_type=\"bdt-social-share.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"bdt-social-share bdt-ep-grid\">\n\t\t\t\t\t\t\t<div class=\"bdt-social-share-item bdt-ep-grid-item\">\n\t\t\t\t\t<div class=\"bdt-ss-btn bdt-ss-linkedin\" data-social=\"linkedin\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"bdt-ss-icon\">\n\t\t\t\t\t\t\t\t<i class=\"ep-linkedin\"><\/i>\n\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"bdt-social-share-item bdt-ep-grid-item\">\n\t\t\t\t\t<div class=\"bdt-ss-btn bdt-ss-twitter\" data-social=\"twitter\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"bdt-ss-icon\">\n\t\t\t\t\t\t\t\t<i class=\"ep-twitter\"><\/i>\n\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"bdt-social-share-item bdt-ep-grid-item\">\n\t\t\t\t\t<div class=\"bdt-ss-btn bdt-ss-facebook\" data-social=\"facebook\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"bdt-ss-icon\">\n\t\t\t\t\t\t\t\t<i class=\"ep-facebook\"><\/i>\n\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\n\t\t\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"has_ma_el_bg_slider elementor-section elementor-top-section elementor-element elementor-element-8ca0303 elementor-section-boxed elementor-section-height-default elementor-section-height-default jltma-glass-effect-no\" data-id=\"8ca0303\" data-element_type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"has_ma_el_bg_slider elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a869007 jltma-glass-effect-no\" data-id=\"a869007\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-08201a5 jltma-glass-effect-no elementor-widget elementor-widget-image\" data-id=\"08201a5\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/techpearl.com\/1719395789229\/wp-content\/uploads\/2025\/05\/blog-cover.png\" class=\"attachment-full size-full\" alt=\"blog cover\" srcset=\"https:\/\/techpearl.com\/1719395789229\/wp-content\/uploads\/2025\/05\/blog-cover.png 1024w, https:\/\/techpearl.com\/1719395789229\/wp-content\/uploads\/2025\/05\/blog-cover-300x169.png 300w, https:\/\/techpearl.com\/1719395789229\/wp-content\/uploads\/2025\/05\/blog-cover-768x432.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"has_ma_el_bg_slider elementor-section elementor-top-section elementor-element elementor-element-30b5d308 elementor-section-boxed elementor-section-height-default elementor-section-height-default jltma-glass-effect-no\" data-id=\"30b5d308\" data-element_type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"has_ma_el_bg_slider elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6d839c4d jltma-glass-effect-no\" data-id=\"6d839c4d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3b59a29f jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"3b59a29f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\tCreating PDFs programmatically is a common need in modern applications, whether for reports, invoices, certificates, or other documents. However, when systems require long-term archiving, regular PDFs are not sufficient. This is where PDF\/A comes in, a specialized version of PDF designed for digital preservation.\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b9db82a jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"b9db82a\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">What is PDF\/A?<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5642bf0 jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"5642bf0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\tPDF\/A is a specialized version of the standard PDF format, created with the primary goal of ensuring the long-term preservation and archiving of electronic documents.\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-02ea8a5 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"02ea8a5\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Key Features of PDF\/A:<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-92390af jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"92390af\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul><li><strong>Self-Contained<\/strong>: All the elements needed to display the document, such as fonts, color profiles, and images, are embedded directly within the file.<\/li><li><strong>No External Dependencies<\/strong>: PDF\/A eliminates the use of features that rely on external content, including audio, video, or JavaScript, ensuring that the document is fully functional without needing external resources.<\/li><li><strong style=\"font-size: 16px;\">Device-Independent<\/strong><span style=\"font-size: 16px;\">: PDF\/A ensures that the document will look the same across different platforms, both now and in the future, preserving its appearance for years to come.<\/span><\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9a59c82 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"9a59c82\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Tools We'll Use<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e2b46cf jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"e2b46cf\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>In this guide, we&#8217;ll:<\/p><ul><li>Generate a PDF from HTML using xhtml2pdf<\/li><li>Convert the resulting PDF to PDF\/A using Ghostscript<\/li><\/ul><p>There are several ways to create PDFs in Python, but in this post, we&#8217;ll focus on using xhtml2pdf to generate a styled PDF from HTML and then convert it to PDF\/A format using Ghostscript.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-44bd2b6 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"44bd2b6\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Generating PDF Using xhtml2pdf<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8331e27 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"8331e27\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Install xhtml2pdf<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e11254f jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"e11254f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>pip install xhtml2pdf<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3c23db3 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"3c23db3\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Create a PDF Template (invoice_template.html)<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-75f438f jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"75f438f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This is a Django compatible HTML template with header, footer, table formatting, and dynamic placeholders:<\/p><p>&lt;!DOCTYPE html&gt;<\/p><p>&lt;html&gt;<\/p><p>&lt;head&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;style&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 body { font-family: Arial, sans-serif; font-size: 12px; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .header, .footer { text-align: center; position: fixed; width: 100%; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .header { top: 0; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .footer { bottom: 0; font-size: 10px; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .content { margin-top: 80px; margin-bottom: 50px; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 table { width: 100%; border-collapse: collapse; margin-top: 20px; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 table, th, td { border: 1px solid #000; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 th, td { padding: 5px; text-align: left; }<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .page-break { page-break-after: always; }<\/p><p>\u00a0\u00a0\u00a0 &lt;\/style&gt;<\/p><p>&lt;\/head&gt;<\/p><p>&lt;body&gt;<\/p><p>\u00a0<\/p><p>&lt;div class=&#8221;header&#8221;&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;img src=&#8221;{{ logo_url }}&#8221; width=&#8221;100&#8243; alt=&#8221;Company Logo&#8221;&gt;&lt;br&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;strong&gt;{{ company }}&lt;\/strong&gt;&lt;br&gt;<\/p><p>\u00a0\u00a0\u00a0 Invoice #: {{ invoice_number }} | Date: {{ date }}<\/p><p>&lt;\/div&gt;<\/p><p>\u00a0<\/p><p>&lt;div class=&#8221;footer&#8221;&gt;<\/p><p>\u00a0\u00a0\u00a0 Page &lt;pdf:page \/&gt; of &lt;pdf:total \/&gt;<\/p><p>&lt;\/div&gt;<\/p><p>\u00a0<\/p><p>&lt;div class=&#8221;content&#8221;&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;p&gt;&lt;strong&gt;Billed To:&lt;\/strong&gt; {{ customer }}&lt;\/p&gt;<\/p><p>\u00a0<\/p><p>\u00a0\u00a0\u00a0 &lt;table&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;thead&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;tr&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;th&gt;Item&lt;\/th&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;th&gt;Qty&lt;\/th&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;th&gt;Price&lt;\/th&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;th&gt;Total&lt;\/th&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/tr&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/thead&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;tbody&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {% for item in items %}<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;tr&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;td&gt;{{ item.name }}&lt;\/td&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;td&gt;{{ item.qty }}&lt;\/td&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;td&gt;${{ item.price }}&lt;\/td&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;td&gt;${{ item.qty|floatformat:2|add:item.price|floatformat:2 }}&lt;\/td&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/tr&gt;<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {% endfor %}<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/tbody&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;\/table&gt;<\/p><p>\u00a0<\/p><p>\u00a0\u00a0\u00a0 &lt;div class=&#8221;page-break&#8221;&gt;&lt;\/div&gt;<\/p><p>\u00a0<\/p><p>\u00a0\u00a0\u00a0 &lt;p&gt;Terms &amp; Conditions:&lt;\/p&gt;<\/p><p>\u00a0\u00a0\u00a0 &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed facilisis nulla at erat vulputate.&lt;\/p&gt;<\/p><p>&lt;\/div&gt;<\/p><p>\u00a0<\/p><p>&lt;\/body&gt;<\/p><p>&lt;\/html&gt;<\/p><p>Replace variables like {{ customer }}, {{ items }}, {{ logo_url }}, etc., with your dynamic context data.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c151b0c jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"c151b0c\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">PDF Render Function in Django<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c36efff jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"c36efff\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Once you&#8217;ve created your HTML template for the PDF, the next step is rendering it dynamically with Django and converting it into a PDF using xhtml2pdf.<\/p><p>Here\u2019s a reusable utility function to do just that:<\/p><p>from django.http import HttpResponse<\/p><p>from django.template.loader import get_template<\/p><p>from xhtml2pdf import pisa<\/p><p>\u00a0<\/p><p>def render_to_pdf(template_src, context_dict={}):<\/p><p>\u00a0\u00a0\u00a0 template = get_template(template_src)<\/p><p>\u00a0\u00a0\u00a0 html = template.render(context_dict)<\/p><p>\u00a0\u00a0\u00a0 response = HttpResponse(content_type=&#8217;application\/pdf&#8217;)<\/p><p>\u00a0\u00a0\u00a0 pisa_status = pisa.CreatePDF(html, dest=response)<\/p><p>\u00a0\u00a0\u00a0 if pisa_status.err:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return HttpResponse(&#8220;Error Rendering PDF&#8221;, status=400)<\/p><p>\u00a0\u00a0\u00a0 return response<br \/><br \/><\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 How It Works:<\/p><ul><li>get_template(template_src) loads your HTML template.<\/li><li>render(context_dict) injects dynamic data.<\/li><li>CreatePDF() converts the HTML to a PDF and writes it directly to the HttpResponse object.<\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f0f0943 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"f0f0943\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Convert PDF to PDF\/A Using Ghostscript<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1f74ae5 jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"1f74ae5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>After generating the PDF, convert it to PDF\/A using Ghostscript (which must be installed):<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-20ed847 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"20ed847\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Install Ghostscript (Linux)<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9f3247c jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"9f3247c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul><li>sudo apt install ghostscript<\/li><li>PDF to PDF\/A Conversion Command<\/li><\/ul><p>def convert_pdf_to_pdfa(input_buffer):<\/p><p>\u00a0\u00a0 logger = hlogger.hlogger()<\/p><p>\u00a0\u00a0 logger.setflow(&#8216;convert_pdf_to_pdfa&#8217;)<\/p><p>\u00a0\u00a0 try:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logger.info(&#8220;Initiating PDF\/A conversion process&#8221;)<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 output_buffer = io.BytesIO()<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 with tempfile.NamedTemporaryFile(suffix=&#8217;.pdf&#8217;, delete=False) as temp_input, \\<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tempfile.NamedTemporaryFile(suffix=&#8217;.pdf&#8217;, delete=False) as temp_output:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em># Write input buffer content to temporary file<\/em><\/p><p><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em>temp_input.write(input_buffer.getvalue())<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 temp_input.flush()<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em># Prepare Ghostscript command<\/em><\/p><p><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em>gs_command = [<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;gs&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dPDFA=1&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dBATCH&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dNOPAUSE&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-sDEVICE=pdfwrite&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-sOutputFile=&#8221; + temp_output.name,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-sColorConversionStrategy=UseDeviceIndependentColor&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dPDFACompatibilityPolicy=1&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dAutoRotatePages=\/None&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dEmbedAllFonts=true&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;-dSubsetFonts=false&#8221;,<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 temp_input.name<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ]<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em># Execute conversion<\/em><\/p><p><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em>with open(os.devnull, &#8220;w&#8221;) as fnull:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 subprocess.check_call(gs_command, stdout=fnull, stderr=fnull)<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 with open(temp_output.name, &#8216;rb&#8217;) as f:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 output_buffer.write(f.read())<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 output_buffer.seek(0)<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logger.info(&#8220;PDF\/A conversion completed successfully&#8221;)<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return output_buffer<\/p><p>\u00a0\u00a0 except subprocess.CalledProcessError as e:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logger.error(&#8220;Ghostscript conversion failed: %s&#8221; % str(e))<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return None<\/p><p>\u00a0\u00a0 except Exception as e:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logger.error(&#8220;Failed to initialize conversion process: %s&#8221; % str(e))<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return None<\/p><p>\u00a0\u00a0 finally:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <em># Clean up temporary files<\/em><\/p><p><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em>for temp_file in (temp_input.name, temp_output.name):<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if os.path.exists(temp_file):<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 os.unlink(temp_file)<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 except Exception as e:<\/p><p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 logger.error(&#8220;Failed to clean up file %s: %s&#8221;% (temp_file, str(e)))<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cc445d3 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"cc445d3\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Why Use a Custom Ghostscript Wrapper for PDF\/A Conversion?<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"has_ma_el_bg_slider elementor-section elementor-top-section elementor-element elementor-element-6b3bffd elementor-section-boxed elementor-section-height-default elementor-section-height-default jltma-glass-effect-no\" data-id=\"6b3bffd\" data-element_type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"has_ma_el_bg_slider elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-21e2aff jltma-glass-effect-no\" data-id=\"21e2aff\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b98698b jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"b98698b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\tEven though there are Python libraries like ghostscript, PyMuPDF, or reportlab that offer some level of PDF handling or Ghostscript integration, using a custom subprocess wrapper around the Ghostscript command-line tool is often the most reliable, flexible, and production-ready solution for PDF\/A conversion.\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"has_ma_el_bg_slider elementor-section elementor-top-section elementor-element elementor-element-f3ac7f4 elementor-section-boxed elementor-section-height-default elementor-section-height-default jltma-glass-effect-no\" data-id=\"f3ac7f4\" data-element_type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"has_ma_el_bg_slider elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9273d5d jltma-glass-effect-no\" data-id=\"9273d5d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-46c1853 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"46c1853\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Full Control Over PDF\/A Compliance<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d0f80e5 jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"d0f80e5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>By calling the Ghostscript CLI directly using subprocess, you gain access to all critical flags and fine-tuned parameters, such as:<\/p>\n<ul>\n<li>-dEmbedAllFonts=true: Ensures fonts are embedded<\/li><li>-sColorConversionStrategy=UseDeviceIndependentColor: Guarantees color fidelity<\/li><li>-dPDFA=1 and -dPDFACompatibilityPolicy=1: Strict PDF\/A compliance<\/li><li>-dAutoRotatePages=\/None: Prevents unexpected page rotation<\/li>\n<\/ul>\n<p>Many Python wrappers expose only a limited subset of these options or abstract away important flags, making it harder to guarantee 100% PDF\/A compliance.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2e8fad6 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"2e8fad6\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Reliable and Battle-Tested<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7412782 jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"7412782\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The Ghostscript CLI has been used for decades in enterprise environments. It&#8217;s:<\/p><ul><li>Stable and maintained<\/li><li>Trusted in compliance-sensitive industries<\/li><li>More feature-complete than any wrapper<\/li><\/ul><p>Using it directly ensures consistent behavior across environments.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-eefc6f1 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"eefc6f1\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Efficient Memory Handling<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8137529 jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"8137529\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The function works with BytesIO memory buffers:<\/p><ul><li>No need to save files permanently to disk<\/li><li>Fits well in web server or API contexts<\/li><li>Handles temporary file cleanup safely with tempfile<\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7446bf9 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"7446bf9\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Enhanced Logging and Error Handling<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-054fe2f jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"054fe2f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Your own wrapper allows you to:<\/p><ul><li>Log exactly what\u2019s happening at each step<\/li><li>Catch and respond to errors gracefully<\/li><li>Provide better debugging and observability<\/li><\/ul><p>Libraries often abstract these details away, making issues harder to track down.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-79041e4 jltma-glass-effect-no elementor-widget elementor-widget-heading\" data-id=\"79041e4\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Cross-Platform and Decoupled<\/h3>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-dbb660d jltma-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"dbb660d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul><li>Works on Linux, macOS, and Windows<\/li><li>No dependency on any specific Python library version<\/li><li>Easier to maintain in Docker or cloud environments<\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Creating PDFs programmatically is a common need in modern applications, whether for reports, invoices, certificates, or other documents. However, when systems require long-term archiving, regular PDFs are not sufficient. This is where PDF\/A comes in, a specialized version of PDF designed for digital preservation. What is PDF\/A? PDF\/A is a specialized version of the standard &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"\" href=\"https:\/\/techpearl.com\/1719395789229\/creating-pdf-and-converting-to-pdf-a-using-python-and-ghostscript\/\"> <span class=\"screen-reader-text\">Creating PDF and Converting to PDF\/A using Python and Ghostscript<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":15,"featured_media":20506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63,16],"tags":[],"class_list":["post-20488","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-django"],"_links":{"self":[{"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/posts\/20488","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/comments?post=20488"}],"version-history":[{"count":20,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/posts\/20488\/revisions"}],"predecessor-version":[{"id":20515,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/posts\/20488\/revisions\/20515"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/media\/20506"}],"wp:attachment":[{"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/media?parent=20488"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/categories?post=20488"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techpearl.com\/1719395789229\/wp-json\/wp\/v2\/tags?post=20488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}