Vous avez vu, dans les chapitres précédents, comment créer une application Flask, la configurer et intégrer des fonctionnalités intéressantes telles que l'authentification par Facebook.
Dans ce chapitre vous ajouterez la dernière fonctionnalité manquante : la génération d'une image à partager sur Facebook.
Cette image contiendra le prénom de la personne suivi de la description trouvée préalablement.
Générez une image de fond
Dans sa documentation, Facebook conseille que les images à partager aient les dimensions suivantes : 1 200 x 630 pixels.
L'image basique sera donc un rectangle de 1200 x 630 pixels coloré en bleu turquoise (une des couleurs du template).
Créez une nouvelle classe dans utils.py
.
utils.py
class OpenGraphImage:
def __init__(self, first_name, description):
self.base()
def base(self):
# create a basic image
pass
Puis utilisez la librairie Pillow (Python Imaging Library) pour générer l'image.
Commencez par l'installer en utilisant PIP :
$ pip install Pillow
La librairie contient un module Image
qui fait exactement ce que nous souhaitons :
utils.py
from PIL import Image
...
class OpenGraphImage:
def __init__(self, first_name, description):
background = self.base()
def base(self):
img = Image.new('RGB', (1200, 630), '#18BC9C')
return img
Afin de visualiser l'image créée, utilisez la méthode show()
.
class OpenGraphImage:
def __init__(self, first_name, description):
background = self.base()
background.show()
Il est temps de tester !
Commencez par commenter la partie du script qui concerne les modèles pendant un bref instant et créez une instance à la fin :
utils.py
# import random
from PIL import Image
# from fbapp.models import Content
#
# def find_content(gender):
# contents = Content.query.filter(Content.gender == Content.GENDERS[gender]).all()
# return random.choice(contents)
...
description = """
Toi, tu sais comment utiliser la console ! Jamais à court d'idées pour réaliser ton objectif, tu es déterminé-e et persévérant-e. Tes amis disent d'ailleurs volontiers que tu as du caractère et que tu ne te laisses pas marcher sur les pieds. Un peu hacker sur les bords, tu aimes trouver des solutions à tout problème. N'aurais-tu pas un petit problème d'autorité ? ;-)
"""
OpenGraphImage('Céline', description)
Puis exécutez le script :
$ python fbapp/utils.py
L'image apparaît ! Youpi !
Écrivez sur une image
La seconde étape consiste à écrire deux éléments sur l'image de base : le prénom et la description.
Écrivez le prénom
Créez une nouvelle méthode : print_on_image()
qui prend plusieurs arguments : l'image de base sur laquelle écrire, le texte, la taille de police et la position dans l'image de base.
Créez une instance, pour le prénom, dont la taille de police est égale à 70px.
La hauteur représente la coordonnée, en ordonnée, à partir de laquelle le logiciel commence à tracer des lettres. Indiquez "50" afin de commencer à écrire à 50px du bord supérieur.
utils.py
class OpenGraphImage:
def __init__(self, first_name, description):
background = self.base()
self.print_on_img(background, first_name.capitalize(), 70, 50)
background.show()
def print_on_img(self, img, text, size, height):
pass
Puis nous utilisons deux nouveaux modules de la librairie : ImageFont
et ImageDraw
.
ImageFont
permet d'utiliser une police de caractère personnalisée et ImageDraw
de dessiner sur une image.
Dois-je installer une nouvelle police ? On n'en a aucune dans le projet, si ?
Vous n'avez rien à installer ! Regardez dans le dossier static/fonts
! ;-)
utils.py
# Nous avons besoin d'interagir avec le système pour charger la police de caractère.
import os
from PIL import Image, ImageFont, ImageDraw
...
class OpenGraphImage:
...
def print_on_img(self, img, text, size, height):
# On commence par charger la police utilisée.
font = ImageFont.truetype(os.path.join('fbapp', 'static', 'fonts', 'Arcon-Regular.otf'), size)
# Création d'une nouvelle instance
draw = ImageDraw.Draw(img)
# textsize renvoie la largeur et la hauteur en pixel
# d'une chaine de caractères donnée.
w, h = draw.textsize(text, font)
# Calcul de la position pour que le texte soit centré
# et non pas aligné à gauche.
position = ((img.width - w) / 2, height)
# Ajout du texte à l'image.
draw.text(position, text, (255, 255, 255), font=font)
Lancez le script... et ça fonctionne !
Écrivez la description
Écrire la description demande un peu plus de réflexion. Avez-vous trouvé pourquoi ?
Si vous exécutez le script en passant en paramètres une phrase assez longue, Python renverra une erreur. En effet, vous essayez d'écrire hors de l'image !
Il faut donc :
découper la phrase d'origine en plusieurs sous-phrases,
imprimer ces dernières sur l'image.
Voici notre solution :
utils.py
import textwrap
class OpenGraphImage:
def __init__(self, first_name, description):
...
# textwrap découpe une chaine de caractères
# sans couper les mots au milieu.
sentences = textwrap.wrap(description, width=60)
# current_h : Hauteur à laquelle commencer à écrire .
# pad : pixels à ajouter entre chaque ligne, en hauteur.
current_h, pad = 180, 10
for sentence in sentences:
w, h = self.print_on_img(background, sentence, 40, current_h)
# on incrémente la hauteur pour créer une nouvelle ligne
# en-dessous.
current_h += h + pad
background.show()
def print_on_img(self, img, text, size, height):
...
# Nous devons renvoyer la largeur et la hauteur
# pour imprimer le texte.
return (w, h)
Lancez le script et admirez votre travail ! :-)
Renvoyez le chemin vers l'image dans la vue
L'image est créée mais comment l'enregistrer ?
Utilisez la méthode save()
qui prend en paramètres le chemin vers le dossier où enregistrer l'image.
Créez une nouvelle méthode protégée, _path
, qui renverra ce chemin :
utils.py
class OpenGraphImage:
# nous ajoutons le paramètre uid
def __init__(self, uid, first_name, description):
...
background.save(self._path(uid))
def _path(self, uid):
# Le nom de l'image est l'identifiant Facebook de la personne.
# Cela nous garantit de ne pas avoir de doublon.
return os.path.join('fbapp', 'static', 'tmp', '{}.jpg'.format(uid))
Enfin, ajoutez une nouvelle méthode qui renverra le nom de l'image uniquement :
utils.py
class OpenGraphImage:
def __init__(self, uid, first_name, description):
self.location = self._location(uid)
# ...
def _location(self, uid):
return 'tmp/{}.jpg'.format(uid)
Vous pouvez désormais utiliser cette méthode dans la vue !
views.py
from .utils import find_content, OpenGraphImage
...
@app.route('/result/')
def result():
...
img = OpenGraphImage(uid, user_name, description).location
Comment vérifier que le script fonctionne ?
Lancez le serveur et allez sur l'URL suivante :
http://localhost:5000/result/?first_name=C%C3%A9line&id=1933433063608371&gender=female
Elle devrait se charger normalement.
Ouvrez l'inspecteur et regardez le contenu du head
: vous devriez voir que la balise méta og:url
contient désormais votre nouvelle image !
Copiez l'URL de la balise et collez-la dans la barre de navigation. Elle devrait ressembler à celle-ci :
http://localhost:5000/index/?img=tmp%2F1933433063608371.jpg
Là encore, regardez le contenu du head
: la balise méta og:image
devrait maintenant contenir votre toute nouvelle photo de couverture ! L'URL devrait ressembler à la suivante :
http://localhost:5000/static/tmp/1933433063608371.jpg
D'ailleurs, vous ne trouvez pas que tester tout ceci devient un peu contraignant ? Moi, si. J'ai bien envie de tester le parcours utilisateur afin de ne plus avoir à le faire à la main.
Récupérez le code du chapitre
Retrouvez l'intégralité du code de ce chapitre à cette adresse.
En résumé
Dans ce chapitre, vous avez vu comment :
Générer et manipuler une image grâce à la librairie externe Pillow
Pillow est disponible depuis le gestionnaire de paquets Pypi
Pour travailler sur une image, Pillow vient avec les objets
Image
,ImageFont
etImageDraw
Créer le chemin d’une image et le retourner dans une vue Flask
Utiliser le module
os
de Python pour manipuler des cheminsAjouter un paramètre avec l’image dans la fonction
render_template()
de la vue pour la passer au template
Tester de manière simple l’application en ouvrant l’inspecteur de code du navigateur
Cela permet de vérifier le contenu des balises HTML généré par le template
Votre application web est désormais fonctionnelle ! Il ne reste plus qu’à la tester et à la déployer en production, mais avant cela, vérifiez que vous avez bien compris les notions vues dans cette partie avec le quizz qui suit.