momente şi schiţe de informatică şi matematică
To attain knowledge, write. To attain wisdom, rewrite.

Un exerciţiu de editare HTML, cu SQL şi Python

HTML | MySQL | Python
2012 mar

Aveam nevoie să inserăm într-o pagină HTML un element <select> conţinând ca opţiuni cele 41 de judeţe, dar menţionând pentru fiecare şi numărul de localităţi (de exemplu, <option value='1'>Alba 717</option>) - a vedea link-ul Localităţi, de pe bara din dreapta a acestei pagini. Judeţele şi localităţile sunt înregistrate în baza de date wikiloc, constituită cum am arătat anterior.

Desigur că editarea manuală este neconvenabilă (<select>-ul va trebui reeditat manual la orice modificare a numărului de localităţi, sau chiar a denumirii judeţului). Soluţia pe care o redăm este tipică pentru acest gen de necesităţi (fiind şi independentă de framework-uri - django, Symfony, etc.).

Constituim fişierul ed_select.sql, conţinând comanda MySQL necesară pentru extragerea datelor:

select judet.id as "ID", 
       judet.nume as "Judeţ", 
       count(*) as "Loc." 
    from localitate, judet 
    where judet.id = localitate.judet_id 
    group by judet.id 
    order by judet.nume

Lansăm interpretorul mysql, indicând baza de date, fişierul cu comenzile SQL de executat asupra acesteia şi un fişier de creat pentru rezultatele execuţiei:

vb@vb:~$ mysql wikiloc < ed_select.sql > ed_select.txt

În fişierul ed_select.txt rezultat:

ID	Judeţ	Loc.
1	Alba	717
2	Arad	283
...

itemurile de pe fiecare linie sunt separate prin caracterul TAB ('\t', de cod ASCII 9). În programul Python următor se citeşte fişierul şi se înlocuiesc toate caracterele TAB cu câte un spaţiu; bufferul respectiv este apoi "splitat" la caracterul '\n' ("end-line"), rezultând lista "rows".

Apoi, fiecare element rows[i] (ignorându-l pe primul, "ID Judeţ Loc.") este scindat la caracterul spaţiu şi valorile rezultate (ID-ul, numele, numărul de localităţi) sunt ambalate corespunzător într-un şir care defineşte un element <option>, şir care este adăugat în lista "html".

# -*- coding: utf-8 -*-
import codecs   # asigură operaţii I/O cu text Unicode ("utf-8")

f = codecs.open("ed_select.txt", "r", "utf-8")
rows = f.read().expandtabs(1).splitlines() # print rows[0]; print rows[1]
f.close()

i, n, html = 1, len(rows), []
while(i < n):
    jid, jud, loc = rows[i].split() # print jid, jud, loc
    html.append("<option value=\'" + jid + "\'>" + jud + " " + loc + "</option>")
    i = i + 1

out = codecs.open('ed_select.html', 'w', 'utf-8')
out.write(''.join(html))
out.close()

Desigur, programul se poate scrie mai concis (şi mai elegant) folosind list comprehension - înlocuind secvenţa while (plus variabilele i, n, html) de mai sus cu:

rws = [row.split() for row in rows]  #print rws[1]
html = ["<option value=\'" + w[0] + "\'>" + w[1] + " " + w[2] + "</option>" 
        for w in rws[1:] ]

În final, lista "html" a fost înscrisă (după transformare în şir) în fişierul ed_select.html:

<option value='1'>Alba 717</option><option value='2'>Arad 283</option>...

Utilizând Firefox, această listă se poate vedea cu următorul procedeu elementar: click "Localităţi" (vezi containerul de aplicaţii de pe bara laterală); selectăm cu mouse-ul elementele apărute; click-dreapta şi alegem opţiunea View Selection Source. - nu se mai poate vedea: în 2018 am eliminat aplicaţia "Localităţi"

Desigur - asigurarea funcţionalitaţii intenţionate (la click pe un judeţ din <select>-ul constituit, să se afişeze lista localităţilor corespunzătoare) ţine de-acum de framework-ul folosit şi eventual, de vreo bibliotecă javaScript.

În cazul de faţă, se lansează o funcţie jQuery - sursa ei se poate vedea deasemenea, cu procedeul indicat mai sus - care transmite unei anumite funcţii ("view", în termeni django) de pe server valoarea atributului "value" din opţiunea selectată; view-ul respectiv obţine de la MySQL localităţile aferente acelui judeţ, ambalează numele în taguri <li> şi returnează lista; funcţia jQuery care postase id-ul încheie prin înscrierea răspunsului în pagină.

vezi Cărţile mele (de programare)

docerpro | Prev | Next