Using the Jinja template in combination with Python automatically generates report files from the form

Tram Ho

Introductions

A long time ago, my team received a request to build a system to automatically generate report files (pdf) by filling input data into predefined positions in existing templates. available. Report file after birth, automatically pushed to the predefined FTP server.

Note: These are hypothetical data and are based on a true story.

The report file has a format like this:

The input data is json data:

With the above input and output requirements, our team resolved quite quickly with a simple solution (quick work also takes achievements):

  • Making an input API. Examine the input data, if there is an error then return the error message.
  • The report generation is done in a “big hand” way: Write a template part with HTML code, then use Python’s format string function to gradually push the data into the HTML file.
  • Convert HTML file into PDF and push it to storage server.

At first, everything seemed to be going smoothly. The business side then adds the requirements:

For the content:

  • If gender is male, display as “Mr.”, female as “Grandma”, without gender data then leave blank.
  • If moneyRemain> 3 only appears:

It is expected to be sufficient to maintain the service in the next week .

  • If 1 <moneyRemain <= 3, the following message will appear:

It is expected to be sufficient to maintain the service in the next week .
Please add money to your deposit account so that the services can be provided on demand.

  • If moneyRemain = 1 and cashRemain <paymentTotal (equal to the total amount payable in the latest week), the following message will appear:

It is not enough to maintain the service for the next week .
Please add money to your deposit account so that the services can be provided on demand.

About the function:

  • Businesses want to change the small components of the report such as: Font, font size, font style, conditions generating notifications (according to the number of serviceRemain) without going through dev or dev team Need to upgrade back-end.
  • More types of forms will arise and the input provider agrees to push one more reportType data field for us to classify.

After receiving the above request, we have been discussing for a long time (actually arguing with garlic) to come up with solutions for handling report generation from template.

Because it is not possible to constantly upgrade the back-end to run the business forever, it will choose a data processing solution in the template.

After many final considerations, we chose Jinja2 template + Python. Why, please read on below.

Note: Within the scope of this article, I will introduce you about Jinja2, the html2pdf section I will introduce in another article.

Introducing Jinja2 template

Jinja2 is a template creation language for Python programmers, created based on the idea of ​​Django template.

Jinja2 is used to create HTML, XML or other file formats based on the principle of combining data into marked locations in the text.

For example:

There are templates:

When transmitting data:

The results are obtained:

For information about Jinja, you can refer to https://jinja.palletsprojects.com/ .

One characteristic of Python support libraries that I like quite a lot is that the libraries are built very “mindfully” with full documentation describing functions and how to effectively use the library. Jinja2 is no exception, you can learn all about Jinja2 at the above link: From data types, loop handling, branching, …

The advantages of Jinja2, you can learn to read at: https://palletsprojects.com/p/jinja/

Apply Jinja2 to solve the automatic report generation problem

Instead of describing some functions of jinja2 with some samples as on the document page of jinja2, I will introduce you by solving the above problem with jinja2 step by step like the way I did a demo to convince the You are on the same team.

Install Jinja2

To start using Jinja2, you can install the following command:

Normally people usually use jinja2 in flask to perform server-side render of html code returned to client. In this article, I will use another jinja2 function to generate the .html file

Initialize project for sample code

First, I will create the directory containing the source code, in this directory put 3 files:

  • input.json: Contains json data file as input of report
  • template.html: Contains html source code which is a form for jinja2 to put data into.
  • jinja_render.py: Contains python code to get data from input.jon and template.html to create report.html file.

To start, open the template.html file and enter the content

Open jinja_render.py file, enter the code:

Standing from the environment containing jinja2, execute the file jinja_render.py

python jinja_render.py

create report.html success!

Open the folder containing the code, file report.html, open the file to view the content

We have used the following components of jinja2 in python:

  • Class Template
  • Function render The task of file jinja_render.py has completed. From here on, the next part of the problem will be focused on using jinja language on template.html

Familiarize yourself with the Jinja2 programming language

Jinja2 provides 2 syntaxes to mark the use of enginee in processing:

{{}}: Display data of variables.

{% keyword%}: Start a processing block. For common keywords: if / else / elif / endif, for / endfor, set, …

{# commnet #} Represents the beginning and end of the comment.

To familiarize yourself with how to use it, I invite you to take turns going into the small sections below.

Put data into the template

The jinja template’s Syntax to place data somewhere in the template is {{ variable_name }}

Where variable_name is the data name of the variable data passed from the input.

Returning to the sample above, our Python sample code will take customerName data from the json file into position {{customerName}} on template.html

Types of control structures (List of Control Structures)

The control structure is the direction of the operation flow of a program, in Jinja2 provides the control structures (Control Structures) as follows: if / elif / else, for-loop, marco, … Use default syntax The control commands will be in the {%%} pair and divided into blocks based on the endif, endfor, and so on. Syntax and Jinja2’s keywords are relatively similar to the Python programming language (as if they were meant for each other).

Branch control in Jinja2

In this section, our sample will handle a request:

The Syntax of the branch statement is used as follows:

The {% %} represents the start of a jinja2 script, escaping by curly brackets and returning to the data section of the HTML / content of the corresponding file.

As the example above, we can see the jinja2 fork syntax is similar to Python.

Back to the example above, we can understand that if any condition is satisfied, the corresponding text data will be displayed below.

When passed to gender == Male (as in json file), the corresponding data is generated in file report.html

For-loop structure

In this section, our sample will handle a request:

With the above problem, we have paymentRequest is a list (array) with each child item as a dictionary. The jinja2 for-loop structure will retrieve each item within the paymentRequest and further access the data fields of each item.

We will put a script using for-loop into the template file and run the file

Results

As the example above, an item subsection is a dictinoray, we can access each value by syntax:

item.cash or item['note']

So we have retrieved the data of the subsections, now one thing is column No.

Jinja2 provides a way to access the index of a list (actually more convenient than Python).

Looking at the table above, we can see that we can use loop.index to type the STT for each row of data.

In the for-loop block code, loop.index , loop.index0 , … are called special variables .

Applying to the above problem, we make changes to template.html by adding the body of the code:

Results

In this display there are 2 issues to solve:

  • Format the amount of missing sign. separate between three-digit clusters (thousand, million)
  • The last row of the table contains the total amount.

We will continue processing below.

Use built-in functions

To calculate the total sum, in theory, we will add up the amount of each subsection and fill in the last line.

Jinja2 provides a function to perform the sum of values ​​in a list or for each attribute of the elements in the list.

We can refer to these functions at the following link: https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-filters

Back to our math problem, the calculation of the total sum is extremely simple based on the function: sum

Syntax performs the format of numbers and strings in jinja2 just like python.

For example to make display a number with accents . is the separator thousands, the sign , is the decimal separator, showing 2 numbers after the decimal point:

The results are obtained:

The amount in Vietnam uses the stamp . As a separator value, we will do some more “circle” replacements … Perform replace sign . into # , into . , Sign # a , .

The inclusion of such a long paragraph on the template seems a bit … bad so jinja2 will support us a block type of Marco

Self-defining functions by marco

In this section, we will create a marco together that adds a thousand separator to the money.

The marco definition is used according to the syntax

Varargs, kwargs are used as function definitions of python 😊

Let’s see the example below:

Applying to our problem, we added the above marco to the code and made changes to the contents of the table

Results:

Put data into temporary variables

In the above example, we see the total payment will be used on the request below. In order to not have to call multiple times in the function sum (), we will perform assigning the total amount to a variable named total as the code below.

Of course the results have not changed.

Perfectly solve the problem

My article is quite long and most of Jinja2’s common syntaxes are given above, so the code below will complete the problem. Thank you for your continued reading.

The final results show:

Epilogue

In addition to processing the report form as above, Jinja2 also applies in many different ways.

For example, you have a database, each data sheet you will have to rewrite the functions for CRUD, update the database, the basic interface, …. Take some time, write a template, then simply pass into a data table structure or write a complete application connected to the database, read out the schema and then generate the necessary files.

Thank you for reading my article. See you again in the next article.

Share the news now

Source : Viblo