issue160:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue160:python [2020/08/29 18:32] – créée auntiee | issue160:python [2020/09/06 14:59] (Version actuelle) – andre_domenech | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | Welcome back. I truly hope that everyone is healthy. Here in central Texas, it’s been hot. Air temperature of 104°F (40°C) with a heat index well over 107 for days, and it’s expected to continue for at least the next 7 days. | + | **Welcome back. I truly hope that everyone is healthy. Here in central Texas, it’s been hot. Air temperature of 104°F (40°C) with a heat index well over 107 for days, and it’s expected to continue for at least the next 7 days. |
Last month, I started showing you the pyFPDF library. This month (FCM #160), we will be continuing to look at this library and examining the Templating portion of the library. | Last month, I started showing you the pyFPDF library. This month (FCM #160), we will be continuing to look at this library and examining the Templating portion of the library. | ||
- | My assumption was that the Templating feature was originally designed to handle things like invoices and labels. Furthermore, | + | My assumption was that the Templating feature was originally designed to handle things like invoices and labels. Furthermore, |
- | I’ll start with a sample of a recipe from my cookbook database that represents a “normal” single page recipe that would or could be printed. In its current “state”, | + | Bonjour, j' |
+ | |||
+ | Le mois dernier, j'ai commencé à vous montrer la bibliothèque pyFPDF. Ce mois-ci (le FCM n° 160), nous continuerons à regarder cette bibliothèque et examinerons sa partie « Template ». | ||
+ | |||
+ | Ma supposition était que la fonctionnalité Template avait été conçue au départ pour gérer des choses comme des factures et des étiquettes. De plus, je pensais qu' | ||
+ | |||
+ | **I’ll start with a sample of a recipe from my cookbook database that represents a “normal” single page recipe that would or could be printed. In its current “state”, | ||
Not the prettiest, I have to admit, but it does the job and handles situations where a user needs a paper copy of the recipe (like if a friend who just can’t live without the recipe) as well as recipes that have lots of ingredients and/or lots of instructions, | Not the prettiest, I have to admit, but it does the job and handles situations where a user needs a paper copy of the recipe (like if a friend who just can’t live without the recipe) as well as recipes that have lots of ingredients and/or lots of instructions, | ||
- | Back to the pyFPDF library; at first glance, the documentation is fairly sparse when it comes to some of the options. Most of it made sense and seemed to be reasonably easy to translate into what I was hoping to do. Well, I was really wrong. It IS sparse and some of the information is confusing. I’ll address this as we go. | + | Back to the pyFPDF library; at first glance, the documentation is fairly sparse when it comes to some of the options. Most of it made sense and seemed to be reasonably easy to translate into what I was hoping to do. Well, I was really wrong. It IS sparse and some of the information is confusing. I’ll address this as we go.** |
- | Since I almost always provide the code and most everything you need to run the demos I create for these articles, I didn’t want to attempt to provide the entire database. There are over 300 recipes and images (in a separate folder), and I really don’t think that pastebin will let me upload a sql database and that many images (or images at all). Therefore, I created a simple program to extract 3 “normal” single-page recipes and hard coded them into a series of “records” which are then dumped into lists for each table. Then, with a printout of the recipes on my clipboard and my ruler in hand, I started to dissect the XY coordinates of where I wanted to put each of the elements. | + | Je commencerai avec un échantillon de recette sorti de la base de données d'un livre de cuisine, qui représente une recette sur une seule page « normale » lors d'une éventuelle impression. Dans son « état » actuel, le programme du livre culinaire crée une page html à la volée, basée sur la recette qui doit être imprimée, puis l' |
- | I decided to use the hardcode method of defining the elements rather than the CSV method, since I wasn’t sure how everything would work and fit together. If it worked, then I could always create | + | Pas la plus jolie, je dois l' |
- | Due to the use of f-strings, you will need to use Python 3.7.4 or greater. | + | Revenons à la bibliothèque pyFPDF ; à première vue, la documentation est plutôt maigre pour certaines des options. Elle était généralement compréhensible et semblait être assez facile à traduire pour ce que je souhaitais faire. Eh bien, je me trompais vraiment. Elle EST maigre et certaines informations prêtent à confusion. Je vous en parlerai au fur et à mesure de notre progression. |
+ | |||
+ | **Since I almost always provide the code and most everything you need to run the demos I create for these articles, I didn’t want to attempt to provide the entire database. There are over 300 recipes and images (in a separate folder), and I really don’t think that pastebin will let me upload a sql database and that many images (or images at all). Therefore, I created a simple program to extract 3 “normal” single-page recipes and hard coded them into a series of “records” which are then dumped into lists for each table. Then, with a printout of the recipes on my clipboard and my ruler in hand, I started to dissect the XY coordinates of where I wanted to put each of the elements. | ||
+ | |||
+ | I decided to use the hardcode method of defining the elements rather than the CSV method, since I wasn’t sure how everything would work and fit together. If it worked, then I could always create a CSV directly later on. I’m really glad I didn’t. You’ll understand later.** | ||
+ | |||
+ | Puisque je fournis presque toujours le code et la plupart des choses dont vous avez besoin pour faire tourner les démos que je crée pour ces articles, je ne voulais pas tenter de vous fournir toute la base de données. Il y a plus de 300 recettes et images (dans un dossier séparé), et je ne pense vraiment pas que pastebin me laissera téléverser une base de données sql et autant d' | ||
+ | |||
+ | J'ai décidé d' | ||
+ | |||
+ | **Due to the use of f-strings, you will need to use Python 3.7.4 or greater. | ||
I started with the header and recipe title. That went pretty well and I was able to get those two elements defined. With one of the sample programs, I started to copy and paste from their sample into my code. | I started with the header and recipe title. That went pretty well and I was able to get those two elements defined. With one of the sample programs, I started to copy and paste from their sample into my code. | ||
- | Shown right is a shortened example of the element structure… | + | Shown right is a shortened example of the element structure…** |
- | As you can see, it’s a list of dictionaries. We’ll break one of them down… | + | Du fait de l' |
+ | |||
+ | J'ai commencé avec les fichiers d' | ||
+ | |||
+ | À droite, voici un exemple raccourci de la structure de l' | ||
+ | |||
+ | **As you can see, it’s a list of dictionaries. We’ll break one of them down… | ||
• Name is the name you want to reference it by | • Name is the name you want to reference it by | ||
• Type is the type of element this is defining. The documented options are: ' | • Type is the type of element this is defining. The documented options are: ' | ||
• X1, Y1, X2, Y2 are the xy positions of an imaginary box. Upper left to lower right. | • X1, Y1, X2, Y2 are the xy positions of an imaginary box. Upper left to lower right. | ||
• Next comes the font specifications, | • Next comes the font specifications, | ||
- | • There is also an optional multiline attribute, which, if used, will be the last in the dictionary. | + | • There is also an optional multiline attribute, which, if used, will be the last in the dictionary.** |
- | Now in the documentation, the Type specification shows only these 5 options. | + | Comme vous pouvez le voir, c'est une liste de dictionnaires. Nous en détaillerons une : |
+ | ••Name est le nom par lequel vous voulez y faire référence. | ||
+ | ••Type est le type de l' | ||
+ | ••X1, Y1, X2, Y2 sont les positions xy dans une boîte imaginaire. D'en haut à gauche au bas à droite. | ||
+ | ••Ensuite viennent les spécifications des polices, les définitions de l' | ||
+ | ••Il y a aussi un attribut optionnel pour lignes multiples qui, s'il est utilisé, sera à la fin du dictionnaire. | ||
- | From what I could see from my limited testing, the priority | + | **Now in the documentation, the Type specification shows only these 5 options. However, by digging into the code of the library, there is one other. It is “W” for write. It was added to allow (url) links in templates (using write method), but can be used in other situations. The good news for this option is that it works similar to the function that we created last month called chapter_body. It allows for multiline paragraph type text to be rendered correctly in a “flowing” manner. |
- | I was somewhat concerned about the image type, since the images | + | From what I could see from my limited testing, the priority (Z-Order) doesn’t make a difference what value you use. I didn’t spend a tremendous amount of time on that part of the testing.** |
- | Now, let’s take a look at the Ingredients section of the PDF. I really wanted to have the header and the text of the list to align as left-justified, similar to the printout image at the top of the article. For the list of ingredients | + | Actuellement dans la documentation, la spécification de Type ne montre que ces 5 options. Cependant, en creusant le code de la bibliothèque, il y en a une autre. C'est « W » pour Write (écrire). Elle a été ajoutée pour permettre les liens (URL) dans les modèles (en utilisant la méthode write), mais peut être utilisée dans d' |
- | Shown top right the element definitions for the ingredientshead and ingredientitems, | + | De ce que j'ai pu voir avec mes essais limités, il n'y a pas de différence dans la priorité (l' |
+ | |||
+ | **I was somewhat concerned about the image type, since the images I use are not a standard size. Since most are scraped from the web, some will be in landscape mode and some in portrait mode. Some are rather large and others fairly small. Luckily, the rendering image resizes the image to fit within the bounds set in the XY positioning. | ||
+ | |||
+ | Now, let’s take a look at the Ingredients section of the PDF. I really wanted to have the header and the text of the list to align as left-justified, | ||
+ | |||
+ | J' | ||
+ | |||
+ | Maintenant, jetons un regard à la section Ingredients du PDF. Je voulais vraiment que l' | ||
+ | |||
+ | **Shown top right the element definitions for the ingredientshead and ingredientitems, | ||
Notice that the y1 position for the static text “Ingredients” is at 220 while the ingredient items block is set at 115. To me, this makes no sense. The same thing occurs with the instructions static text and the flowing text of the instructions. | Notice that the y1 position for the static text “Ingredients” is at 220 while the ingredient items block is set at 115. To me, this makes no sense. The same thing occurs with the instructions static text and the flowing text of the instructions. | ||
- | Now that we have our data defined and the elements dictionary set up (see the full code for all the elements definition), | + | Now that we have our data defined and the elements dictionary set up (see the full code for all the elements definition), |
- | So the function definition accepts a parameter called “which”. This will be the index of the recipe within the “database”. We pull the recipe title and the recipe id into separate variables, not only for use now, but also later on. Then we instantiate the template object, defining the title of the document, the format of the printout, and the elements. You can also set properties for the document (author, subject, etc) here as well. Finally, we add a page with the add_page() method. Again, fairly close to what we did last month. | + | Vous voyez en haut à droite la définition des éléments pour ingredientshead (Titre des ingrédients) et ingredientitems (composition) qui est très voisine de la section des instructions : |
+ | |||
+ | Notez que la position y1 pour le texte fixe « Ingredients » est à 220, alors que le bloc des composants est placé à 115. Pour moi, ça n'a pas de sens. La même chose se produit avec le texte fixe des instructions et le texte flottant de celles-ci. | ||
+ | |||
+ | Maintenant que nos données sont définies et que le dictionnaire des éléments est paramétré (voir le code en entier pour la définition complète des éléments), | ||
+ | |||
+ | **So the function definition accepts a parameter called “which”. This will be the index of the recipe within the “database”. We pull the recipe title and the recipe id into separate variables, not only for use now, but also later on. Then we instantiate the template object, defining the title of the document, the format of the printout, and the elements. You can also set properties for the document (author, subject, etc) here as well. Finally, we add a page with the add_page() method. Again, fairly close to what we did last month. | ||
So, to set the various elements in the document, we call the elements that we want to include with, in some cases, a string – one at a time. The format is: | So, to set the various elements in the document, we call the elements that we want to include with, in some cases, a string – one at a time. The format is: | ||
Ligne 48: | Ligne 91: | ||
Object[element] = optional string | Object[element] = optional string | ||
- | The code for that is on the next page, top right. | + | The code for that is on the next page, top right.** |
- | Since there is no straightforward way to handle a list, I stepped through the list of ingredients and created a string, which is then set using the ingredientitems element (bottom left). | + | Ainsi, la définition de la fonction accepte un paramètre appelé « which ». Ce sera l' |
+ | |||
+ | Ainsi, pour paramétrer les différents éléments du document, nous appelons les éléments que nous voulons inclure avec, dans certains cas, une chaîne - une à la fois. Le format est : | ||
+ | |||
+ | Object[element] = chaîne de caractères optionnelle | ||
+ | |||
+ | Le code de cela est sur la page suivante, en haut à droite. | ||
+ | |||
+ | **Since there is no straightforward way to handle a list, I stepped through the list of ingredients and created a string, which is then set using the ingredientitems element (bottom left). | ||
The instructions section is handled the same way. | The instructions section is handled the same way. | ||
Ligne 56: | Ligne 107: | ||
Finally (bottom right), we render the page pretty much as we did last month, but this time, we use the recipe title as the filename for the PDF. After that, we notify the user that the rendering process is complete. | Finally (bottom right), we render the page pretty much as we did last month, but this time, we use the recipe title as the filename for the PDF. After that, we notify the user that the rendering process is complete. | ||
- | Lastly, I needed a way for the program to prompt the user to select which recipe to use. I created a simple CLI based menu (right). | + | Lastly, I needed a way for the program to prompt the user to select which recipe to use. I created a simple CLI based menu (right).** |
+ | |||
+ | Comme il n'y a pas de manière directe de gérer une liste, je suis passé pas à pas dans la liste des ingrédients et j'ai créé une chaîne qui est ensuite paramétrée en utilisant l' | ||
+ | |||
+ | La section des instructions est gérée de la même manière. | ||
+ | |||
+ | Enfin (en bas à droite), nous restituons la page à peu près comme nous le fîmes le mois dernier, mais, cette fois, nous utilisons le titre de la recette comme nom de fichier du PDF. Après ça, nous indiquons à l' | ||
+ | |||
+ | Pour terminer, j' | ||
+ | |||
+ | **And a routine that loops and does the menu until the user uses “0” to quit (middle right). | ||
+ | |||
+ | Well, that’s it. I believe that, as a quick PDF generator that can be controlled easily from Python, pyFPDF is a good tool. However, as a template engine, I’m not convinced that it will work in the real world. Given the fact that the latest code changes were done 3 years ago, I don’t hold out much hope that the author will address the many issues surrounding the template engine. There is a big part of me that wants to fork the project and modify the code myself, but life and time and work (as always) prevent me from doing it right now. Just one more item on the todo list.** | ||
+ | |||
+ | Et une routine qui boucle et présente le menu jusqu' | ||
+ | |||
+ | Bon, c'est tout. Je crois que, en tant que générateur rapide de PDF qui peut être facilement contrôlé en Python, pyFPDF est un bon outil. Cependant, comme moteur de modèle (en anglais, template), je ne suis pas convaincu qu'il fonctionnera dans le monde réel. Étant donné le fait que les dernières modifications du code ont été faites il y a 3 ans, je ne garde pas beaucoup d' | ||
+ | |||
+ | **Normally, I would post the project code, when the project is more than working directly within the Python shell. This month, I am going to break tradition and not post it on Pastebin.com. The reason for this is that I don’t believe that pastebin will allow me to post the image files for the recipes. This is also one of the reasons that I didn’t just directly work from the recipe database, which at the moment, holds over 300 recipes, and for each recipe there is an image. So, I’ve created a repository on Github to hold this month’s project. By doing it this way, all you have to do is follow the link to the repository, download the project as a zip file (you could clone it, but that is, in my mind, a lot of wasted effort on your part), unzip the folder somewhere convenient for you, and run the python program, called template1.py. The link to the repository is https:// | ||
- | And a routine that loops and does the menu until the user uses “0” to quit (middle right). | + | Normalement, |
- | Well, that’s it. I believe that, as a quick PDF generator that can be controlled easily from Python, pyFPDF is a good tool. However, as a template engine, I’m not convinced | + | **One more bit of news before I leave you for this month. As of Wednesday, August 5, I have signed |
- | Normally, I would post the project code, when the project is more than working directly within the Python shell. This month, I am going to break tradition and not post it on Pastebin.com. The reason for this is that I don’t believe that pastebin will allow me to post the image files for the recipes. This is also one of the reasons that I didn’t just directly work from the recipe database, which at the moment, holds over 300 recipes, and for each recipe there is an image. | + | So as always, until next time; stay safe, healthy, positive |
- | One more bit of news before I leave you for this month. As of Wednesday, August | + | Quelques nouvelles de plus avant que je ne vous quitte pour ce mois. Le mercredi |
- | So as always, until next time; stay safe, healthy, positive and creative! | + | Aussi, comme toujours, jusqu' |
issue160/python.1598718762.txt.gz · Dernière modification : 2020/08/29 18:32 de auntiee