<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chukwuemeka Nwaoma</title>
    <description>The latest articles on DEV Community by Chukwuemeka Nwaoma (@joelchuks).</description>
    <link>https://dev.to/joelchuks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F804139%2Fc1a7eca0-75d7-45bf-b1c7-057ce02b631c.jpeg</url>
      <title>DEV Community: Chukwuemeka Nwaoma</title>
      <link>https://dev.to/joelchuks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joelchuks"/>
    <language>en</language>
    <item>
      <title>Django Import and Export (Including PDF)</title>
      <dc:creator>Chukwuemeka Nwaoma</dc:creator>
      <pubDate>Mon, 14 Feb 2022 01:49:52 +0000</pubDate>
      <link>https://dev.to/joelchuks/django-import-and-export-26ad</link>
      <guid>https://dev.to/joelchuks/django-import-and-export-26ad</guid>
      <description>&lt;p&gt;As the name suggests, this project covers a basic import and export in Django using the &lt;em&gt;django-import-export&lt;/em&gt; package.&lt;/p&gt;

&lt;p&gt;I have tried to implement a common feature of importing and exporting data to and from the model via the admin panel while also digging deeper into bringing the export feature to the views and passing it straight to the template.&lt;/p&gt;

&lt;p&gt;While the django-import-export package does not cover exporting to PDF, I have implemented that a PDF export together with a few others like CSV, XLS and JSON and made them downloadable in one selection and click.&lt;/p&gt;

&lt;p&gt;Let's get started with the codes!&lt;/p&gt;

&lt;p&gt;First, set up a Django project with a basic model. In my case, I have made it a bit tougher by creating two related models.&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="https://django-import-export.readthedocs.io/en/latest/api_widgets.html" rel="noopener noreferrer"&gt;https://django-import-export.readthedocs.io/en/latest/api_widgets.html&lt;/a&gt;&lt;br&gt;
to install &lt;em&gt;django-import-export&lt;/em&gt;, then set up the admin import-export mixins.&lt;/p&gt;

&lt;p&gt;Introduce a &lt;em&gt;dehydrate&lt;/em&gt;[field]_ function for fields with foreign keys and instantiate them in the resources class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BookResource(resources.ModelResource):
    author = Field()
    created = Field()

    class Meta:
        model = Book
        fields = ('id', 'title', 'author', 'publish_status', 'created')
        export_order = ('id', 'title', 'author', 'publish_status', 'created')

    def dehydrate_author(self, obj):
        return obj.author.name

    def dehydrate_created(self, obj):
        return obj.created.strftime("%d-%m-%y")


class BookAdmin(ImportExportActionModelAdmin):
    resource_class = BookResource

admin.site.register(Author)
admin.site.register(Book, BookAdmin)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When that is done, you'll notice the import and export buttons on the admin dashboard, and that is all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyio9nwefsnm36c6og4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyio9nwefsnm36c6og4l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, to bring this feature from the views to the template, start off with creating a resources.py file, importing the models, as well as the resources and fields from import_export.&lt;/p&gt;

&lt;p&gt;Write a resources class just like with the admin.py file and write its meta class too.&lt;/p&gt;

&lt;p&gt;Move to the views and use a created form to collect predefined responses, then match each response to a format and return.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# If User Selects CSV Format
            if dataFormat == 'csv':
                book_resource = BookResource()
                dataset = book_resource.export()
                response = HttpResponse(dataset.csv, content_type='text/csv')
                response['Content-Disposition'] = 'attachment; filename="books.csv"'
                return response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the PDF format, import weasyprint and also install GTK3-Runtime if on a windows machine, and don't forget to add to path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # If User Selects PDF Format   
            elif dataFormat == 'pdf':
                # obj = Book.objects.all()
                template = get_template('core/pdf-output.html')
                html = template.render(context)
                response = HttpResponse(content_type='application/pdf')
                result = HTML(string=html).write_pdf(response)
                response['Content-Disposition'] = 'attachment; filename="books.pdf"'
                response['Content-Transfer-Encoding'] = 'binary'
                return response

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an output template, pass the template name to the views, then write pdf, and that's all. Too Easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="jumbotron"&amp;gt;
            &amp;lt;table class="table table-bordered"&amp;gt;
                &amp;lt;thead&amp;gt;
                    &amp;lt;tr&amp;gt;
                        &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;
                        &amp;lt;th style="text-align: center;" colspan="2"&amp;gt;Author&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;Status&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;Date Created&amp;lt;/th&amp;gt;
                    &amp;lt;/tr&amp;gt;    
                    &amp;lt;tr&amp;gt;
                        &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;&amp;lt;em class="text-muted"&amp;gt;Name&amp;lt;/em&amp;gt;&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;&amp;lt;em class="text-muted"&amp;gt;Gender&amp;lt;/em&amp;gt;&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;
                        &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;
                    &amp;lt;/tr&amp;gt;            
                &amp;lt;/thead&amp;gt;
                &amp;lt;tbody&amp;gt;
                    {% for book in obj %}
                        &amp;lt;tr&amp;gt;   
                            &amp;lt;td&amp;gt;{{book.title}}&amp;lt;/td&amp;gt; 
                            &amp;lt;td&amp;gt;{{book.author}}&amp;lt;/td&amp;gt; 
                            &amp;lt;td&amp;gt;{{book.author.gender}}&amp;lt;/td&amp;gt; 
                            &amp;lt;td&amp;gt;{{book.publish_status}}&amp;lt;/td&amp;gt; 
                            &amp;lt;td&amp;gt;{{book.created|date:"M. d, Y"}}&amp;lt;/td&amp;gt; 
                        &amp;lt;/tr&amp;gt;
                    {% endfor %}

                &amp;lt;/tbody&amp;gt;
            &amp;lt;/table&amp;gt;

            &amp;lt;br&amp;gt;

            &amp;lt;div style="display: flex; height: 40px;"&amp;gt;
                &amp;lt;form method="post" style="margin-top: 1px; margin-right: 10px; font-size: medium;"&amp;gt;
                    {% csrf_token %}
                    {{form}}
                    &amp;lt;input type="submit" style="height: 33px;" class='btn btn-primary' value="Go"&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/div&amp;gt;


        &amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnntipdnsxy3orf40d7fr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnntipdnsxy3orf40d7fr.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc2a9ocguh9zi8c6hs3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc2a9ocguh9zi8c6hs3m.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihigmxp2teoi8de0yp6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihigmxp2teoi8de0yp6u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://doc.courtbouillon.org/weasyprint/latest/first_steps.html" rel="noopener noreferrer"&gt;https://doc.courtbouillon.org/weasyprint/latest/first_steps.html&lt;/a&gt; for more details on weasyprint.&lt;/p&gt;

&lt;p&gt;Check out the complete code repo on &lt;a href="https://github.com/joelchooks/import_export" rel="noopener noreferrer"&gt;https://github.com/joelchooks/import_export&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
