issue160:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
issue160:python [2020/09/03 08:57] – d52fr | issue160:python [2020/09/06 14:59] (Version actuelle) – andre_domenech | ||
---|---|---|---|
Ligne 5: | Ligne 5: | ||
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, | ||
- | Bonjour, j' | + | Bonjour, j' |
- | Le mois dernier, j'ai commencé à vous montrer la bibliothèque pyFPDF. Ce mois-ci (FCM n° 160), nous continuerons à regarder cette bibliothèque et examinerons sa partie « Template ». | + | 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' | + | 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”, | **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”, | ||
Ligne 17: | Ligne 17: | ||
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.** | ||
- | Je commencerai avec un échantillon de recette sorti d' | + | 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' |
- | Pas la plus jolie, je dois l' | + | Pas la plus jolie, je dois l' |
- | 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 | + | 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 |
**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. | **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. | ||
Ligne 27: | Ligne 27: | ||
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.** | 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.** | ||
- | Bien que je fournisse | + | Puisque |
- | J'ai décidé d' | + | J'ai décidé d' |
**Due to the use of f-strings, you will need to use Python 3.7.4 or greater. | **Due to the use of f-strings, you will need to use Python 3.7.4 or greater. | ||
Ligne 37: | Ligne 37: | ||
Shown right is a shortened example of the element structure…** | Shown right is a shortened example of the element structure…** | ||
- | Du fait de l' | + | Du fait de l' |
- | J'ai commencé avec les fichiers d'entête | + | J'ai commencé avec les fichiers d'en-tête |
- | À droite, voici un exemple raccourci de la sruvcture | + | À droite, voici un exemple raccourci de la structure |
**As you can see, it’s a list of dictionaries. We’ll break one of them down… | **As you can see, it’s a list of dictionaries. We’ll break one of them down… | ||
Ligne 50: | Ligne 50: | ||
• 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.** | ||
- | Comme vous pouvez le voir, c'est une liste de dictionnaires. Nous en détaillerons | + | Comme vous pouvez le voir, c'est une liste de dictionnaires. Nous en détaillerons |
- | ••Name est le nom par lequel vous voulez y faire référence | + | ••Name est le nom par lequel vous voulez y faire référence. |
- | ••Type est le type de l' | + | ••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. | ••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 | + | ••Ensuite viennent les spécifications |
- | ••Il y a aussi un attribut optionnel pour lignes multiples qui, s'il est utilisé, sera en fin de dictionnaire. | + | ••Il y a aussi un attribut optionnel pour lignes multiples qui, s'il est utilisé, sera à la fin du dictionnaire. |
**Now in the documentation, | **Now in the documentation, | ||
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.** | 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.** | ||
+ | |||
+ | Actuellement dans la documentation, | ||
+ | |||
+ | 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. | **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, | 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, | **Shown top right the element definitions for the ingredientshead and ingredientitems, | ||
Ligne 70: | Ligne 78: | ||
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), | ||
+ | |||
+ | 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 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. | ||
Ligne 78: | Ligne 92: | ||
The code for that is on the next page, top right.** | The code for that is on the next page, top right.** | ||
+ | |||
+ | 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). | **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). | ||
Ligne 86: | Ligne 108: | ||
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). | **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.** | 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:// | **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:// | ||
+ | |||
+ | Normalement, | ||
**One more bit of news before I leave you for this month. As of Wednesday, August 5, I have signed a contract to write another book. This one will be about learning to use PAGE to create GUIs for Python. I’ve written a few articles about PAGE in the past, and I’m sure that I will in the future as well. The working title, at the moment, is ‘Learning Page A GUI Designer for Python’ and I’m estimating that it will be published sometime in January 2021. | **One more bit of news before I leave you for this month. As of Wednesday, August 5, I have signed a contract to write another book. This one will be about learning to use PAGE to create GUIs for Python. I’ve written a few articles about PAGE in the past, and I’m sure that I will in the future as well. The working title, at the moment, is ‘Learning Page A GUI Designer for Python’ and I’m estimating that it will be published sometime in January 2021. | ||
So as always, until next time; stay safe, healthy, positive and creative!** | So as always, until next time; stay safe, healthy, positive and creative!** | ||
+ | |||
+ | Quelques nouvelles de plus avant que je ne vous quitte pour ce mois. Le mercredi 5 août, j'ai signé un contrat pour écrire un autre livre. Celui-ci sera sur l' | ||
+ | |||
+ | Aussi, comme toujours, jusqu' | ||
issue160/python.1599116263.txt.gz · Dernière modification : 2020/09/03 08:57 de d52fr