7.5. HTMLTags - génère du HTML en Python
7.5.1 Vue d'ensemble
Le module HTMLTags définit une classe pour toutes les balises HTML valides, écrites en majuscules. Pour créer un élément en HTML, la syntaxe générale est :
t = TAG(content, key1=val1,key2=val2,...)
de façon que print t
donnera :
<TAG key1="val1" key2="val2" ...>content</TAG>
Par exemple :
print A('bar', href="foo") ==> <A href="foo">bar</A>
Pour les attributs qui ont le même nom que des mots-clé de Python (class
,
type
) il faut les écrire avec une majuscule :
print DIV('bar', Class="title") ==> <DIV Class="title">bar</A>
Pour générer des attributs HTML sans valeur, donnez-leur la valeur
True
:
print OPTION('foo',SELECTED=True,value=5) ==> <OPTION value="5" SELECTED>
Pour des balises sans fermeture telles que <IMG> ou <BR>, l'instruction
print
ne génère pas de balise fermante
7.5.2 Concaténation de balises
Pour ajouter un "frère" à une balise (un élément au même niveau dans l'arborescence) on se sert de l'opérateur d'addition :
print B('bar')+INPUT(name="bar") ==> <B>bar</B><INPUT name="bar">
On peut aussi répéter une instance en utilisant l'opérateur de multiplication :
print TH(' ')*3 ==> <TD> </TD><TD> </TD><TD> </TD>
A partir d'une liste d'instances, on peut concaténer les éléments avec la fonction Sum()
:
Sum([ (I(i)+':'+B(i*i)+BR()) for i in range(100) ])
génère des lignes avec les carrés des entiers de 0 à 99
7.5.3 Construction d'un document HTML
Un document HTML est un arbre constitué d'éléments ; HTMLTags fournit des moyens simples pour construire cet arbre
L'argument content peut être une instance d'une classe de HTMLTags, il est donc possible d'imbriquer des balises de cette façon :
print B(I('foo')) ==> <B><I>foo</I></B>
Si on considère le document comme un arbre, cela veut dire que l'instance I('foo')
est un fils de l'instance de la classe B
Pour construire un arbre plus complexe, en prenant cette approche il faut faire attention aux parenthèses ouvrantes et fermantes, et le code risque de devenir rapidement difficile à lire et à maintenir. Cela implique aussi qu'on construit l'arbre "par le bas"
Une autre solution est de le construire "par le haut" : construire d'abord le premier élément contenant, puis lui ajouter des descendants. HTMLTags se sert de l'opérateur <=
comme synonyme de "ajouter un enfant"
Vous pouvez comparer les deux approches sur cet exemple :
- "par le bas"
# construction des lignes en premier
lines = INPUT(name="zone1",value=kw.get("zone1",""))
lines += BR()+INPUT(name="zone2",value=kw.get("zone2",""))
lines += BR()+INPUT(Type="submit",value="Ok")
# construction et impression du formulaire
print FORM(lines,action="validate",method="post") - "par le haut"
# construction du formulaire en premier
form = FORM(action="validate",method="post")
# ajout des éléments descendants
form <= INPUT(name="zone1",value=kw.get("zone1",""))
form <= BR()+INPUT(name="zone2",value=kw.get("zone2",""))
form <= BR()+INPUT(Type="submit",value="Ok")
print form
Pour construire un document complexe, l'approche par le haut est probablement plus lisible
head = HEAD() head <= LINK(rel="Stylesheet",href="../doc.css") head <= TITLE('Collection de disques')+stylesheet body = BODY() body <= H1('Ma collection de disques') table = TABLE(Class="content") table <= TR(TH('Titre')+TH('Artiste')) for rec in records: table <= TR(TD(rec.titre,Class="titre")+TD(rec.artiste,Class="artiste") body <= table print HTML(head+body)
7.5.4 Inspection de l'arborescence du document
Les balises possèdent 2 méthodes qui permettent de retrouver les éléments descendant de la balise et qui satisfont certaines conditions :
get_by_tag(tag_name)
: renvoie la liste des élements descendants qui ont le nom de balise spécifiéget_by_attr(arg1=val1,arg2=val2...)
: renvoie la liste des éléments descendants dont les attributs satisfont les conditions spécifiées
Par exemple, si vous avez construit une table et que vous voulez présenter les lignes paires et impaires dans des styles différents, vous pouvez utiliser get_by_tag()
et modifier l'attribut "Class" des balises TD
de cette façon :
classes = ['ligne_paire','ligne_impaire'] lignes = table.get_by_tag('TR') for i,ligne in enumerate(lignes): cellules = ligne.get_by_tag('TD') for cellule in cellules: cellule.attrs['Class'] = classes[i%2]
7.5.5 Balises SELECT, cases à cocher et boutons radio
Quand on construit un document HTML, il y a souvent un ensemble de données (le résultat d'une requête à une base de données par exemple) qui doit être présenté à l'utilisateur comme une liste d'options dans une balise SELECT, ou comme une liste de boutons radio ou de cases à cocher. En général, une ou plusieurs des options est sélectionnée ou cochée parce qu'elle remplit certaines conditions
HTMLTags fournit des méthodes spéciales pour la balise SELECT pour l'initialiser à partir de l'ensemble de données, et pour marquer une ou plusieurs options comme sélectionnée :
from_list(data)
: renvoie la balise SELECT avec les balises OPTION construites à partir de la liste data. Chaque balise OPTION a la valeur de l'élément comme contenu et le rang de l'élément dans la liste comme valeur :s = SELECT().from_list(["foo","bar"]) ==>
<SELECT>
<OPTION value="0">foo
<OPTION value="1">bar
</SELECT>select(content=item)
ouselect(value=item)
: marque les options avec le contenu ou la valeur spécifié comme sélectionné, et les autres options comme non sélectionnées. item peut être une liste d'éléments ou de valeurs, pour les balises SELECT qui ont l'option MULTIPLEs.select(content="bar") ==>
<SELECT>
<OPTION value="0">foo
<OPTION value="1" SELECTED>bar
</SELECT>
Pour les cases à cocher et les boutons radio, HTMLTags fournit 2 classes, CHECKBOX
et RADIO
. Les instances de ces deux classes sont initialisées avec une liste comme premier argument, et les attributs des balises INPUT comme autres arguments par mots-clés :
radio = RADIO(["foo","bar"],Class="menu")
L'itération sur une instance de RADIO produit des tuples (contenu,balise)
où contenu est l'élément de la liste originale :
for (contenu,balise) in radio: print contenu,balise==>
bar<INPUT Type="radio" Class="menu" value="1">
Quand l'instance est créée, toutes les balises INPUT sont décochées. La méthode check(content=item)
ou check(value=item)
est utilisée pour cocher les balises INPUT qui ont le contenu ou la valeur spécifié
radio.check(content="foo") table = TABLE() for (contenu,balise) in radio: table <= TR(TD(contenu)+TD(balise)) print table==>
<TABLE> <TR> <TD>foo</TD> <TD><INPUT Type="radio" Class="menu" value="0"></TD> </TR> <TR> <TD>bar</TD> <TD><INPUT Type="radio" Class="menu" value="1"></TD> </TR> </TABLE>
Comme pour SELECT
, item peut être une liste d'éléments ou de valeurs, dans le cas où on veut cocher plusieurs cases à cocher
7.5.6 Unicode
Le contenu et les valeurs d'attributs peuvent être indifféremment des chaînes d'octets ou des chaînes Unicode. Quand une balise est imprimée, les chaînes Unicode sont encodées en chaînes d'octets. L'encodage est défini par la fonction set_encoding(encodage)
Si vous ne spécifiez pas d'encodage, la valeur par défaut du système (sys.getdefaultencoding()
) est utilisée
Dans les scripts Karrigell, l'encodage défini par SET_UNICODE_OUT()
est aussi utilisé par HTMLTags - il n'est pas nécessaire d'utiliser en plus la fonction set_encoding()