bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


playground:prova

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

Següent revisió
Revisió prèvia
Següent revisió Ambdós costats nova versio
playground:prova [2022/12/13 18:42]
enric_mieza_sanchez creat
playground:prova [2022/12/14 19:02]
enric_mieza_sanchez
Línia 1: Línia 1:
-====== Python Web amb Flask ======+====== Cordova ======
  
-Python és un llenguatge amb una gran implantació en l'àmbit acadèmic, de recerca, en particular en intel·ligència artificial, però que també té excel·lents eines per treballar el desenvolupament web. A mésés el llenguatge que més ha prosperat en els darrers anys.+Apache Cordova (inicialment PhoneGap) son unes llibreries per al desenvolupament d'apps mòbils utilitzant [[JavaScript]], [[HTML]] i [[CSS]]. La principal avantatge és que permet utilitzar un llenguatge web genèric (JS) i compilar l'app per a diverses plataformes diferentsd'entre les que destaquem les majoritàries [[Android]] i [[iOS]].
  
-Aquest article resumeix una petita introducció ràpida a com utilitzar el [[https://flask.palletsprojects.com/|microframework Flask]] sobre una màquina Linux Ubuntu/Debian.+El seu funcionament es basa en tenir una aplicació nadiua amb una simple WebView que ocupa tota la pantalla senceraImplementant codi JavaScript dins la WebView ens permetrà controlar la interfície gràficaPer accedir a les funcionalitats pròpies del dispositiu mòbil disposarem de certes llibreries (càmera, filesystem, acceleròmetre, etc).
  
-Python disposa de molts frameworks i microframeworks per webAlguns dels més coneguts: +{{ cordova.png?400 }}
-  - **Flask** : essencial, però amb tot el necessari i ben mantingut +
-  - **Django** : //the framework for perfectionists with deadlines// , permet el desenvolupament molt ràpid, amb eines com el ORM i un admin panel molt potent. +
-  - **CherryPy** : microframework +
-  - **Bottle** : microframework+
  
-Referències: +{{tag> #Dam #DamMp08 #DamMpDual #DawMpDual Android iOS Cordova HTML JavaScript }}
-  * Per desenvolupar en Python necessitarem [[Python venv]] +
-  * L'article segueix a [[Python Web Test]]+
  
-{{tag> #Daw #DawMpDual #DawMp07Uf1 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04 #DawMp07Uf1 #DawMp07Uf02 #DawMp07Uf03 #DawMp07Uf04 #Ciber #CiberMp03 #Ceti #CetiMp03 python web flask }} 
  
-\\+===== Introducció i requisits ===== 
 +Per poder seguir aquest article se suposa que has de tenir coneixements de [[JavaScript]], [[HTML]] i [[CSS]].
  
-===== Videotutorials ===== +Si tens coneixements molt bàsics també t'interessaria [[https://www.w3schools.com/js/js_htmldom.asp|repassar els conceptes del DOM o Document Object Model]].
-Aquest article també el tens en [[https://www.youtube.com/watch?v=bHg1b0XcU3g|dues parts en format vídeotutorial a Youtube]] explicat pas a pas.+
  
-{{youtube>bHg1b0XcU3g}}+Abans de començar a treballar amb Cordova caldrà que tinguem instal·lats els entorns de desenvolupament: llegeix [[Java]] i [[Android]] primerament.
  
-{{youtube>pv1_CPLg4xw}}+Per instal·lar Cordova necessites un bon plegat d'eines. De forma general necessitaràs: 
 +  - **Android Studio** que ens facilitarà les eines de l'Android SDK. 
 +  - **Java 8 JDK** no ens servirà cap altra versió. 
 +  - **NodeJS** que ens facilitarà el gestor de paquets NPM amb el què podrem instal·lar Cordova 
 +  - **Gradle** en la darrera versió.
  
-\\ 
  
-===== Instal·lació ===== +En cas de que puguis treballar en un Machauràs d'instal·lar Xcode (des de la pròpia AppStore) i activar les CLI (Command Line Interface) Tools. En la versió Xcode 10 (High Sierra) seria: 
-Necessitem Python 3, que ja sol venir instal·lat. Si no fos aixípots instal·lar-ho amb:+  XCode -> Preferences -> Locations -> Command Line Tools
  
-  $ sudo apt install python3+MacOS: [[https://evothings.com/doc/build/cordova-install-osx.html|Instal·lació de Cordova per a MacOS]].
  
-Necessitem crear un [[python_venv|entorn virtual de Python]]. La manera més senzilla és:+Tens algun material per [[https://cacauet.org/wiki/index.php/Android|començar amb Cordova a Cacauet.org]]
  
-  $ python -m venv env+\\
  
-I podem activar el nostre entorn amb:+===== Instal·lació en Ubuntu =====
  
-  $ source env/bin/activate+  - Primer cal tenir instal·lat **Anrdoid Studio**:<code>sudo snap install android-studio --classic</code> 
 +    - Prova de crear un projecte dins d'Android Studio i llençar-lo sobre una VM Android (emulador) abans de seguir amb el tutorial. 
 +  - Cal **instal·lar Java 8 JDK, només funcionarà amb aquesta versió** de Java. 
 +    - Vigila que no tens cap altra versió instal·lada. Si la tens, desinstal·la-la. Comprova si la tens amb (ha de sortir-te openjdk version 1.8):<code>$ java -version</code> 
 +    - Instal·la Java 8 JDK:<code>$ sudo apt install openjdk-8-jdk</code> 
 +    - Ajusta la variable d'entorn ''ANDROID_SDK_ROOT'':<code>$ export ANDROID_SDK_ROOT=~/Android/Sdk</code> 
 +    - Millor que afegeixis aquest export a l'arxiu ''~/.profile'' (afegiu-lo al final del fitxer). Si no, caldrà que facis l'export cada cop que obris una //shell// per treballar amb Cordova. 
 +  - Necessitarem **instal·lar NodeJS**, no pel servidor web, sinó perquè necessitem el gestor de paquets ''npm'': 
 +    - Canviem repos per [[https://github.com/nodesource/distributions/blob/master/README.md|descarregar la versió LTS]]:<code>$ curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -</code> 
 +    - Instal·lar nodejs:<code>$ sudo apt install nodejs</code> 
 +  - Instal·lar **Cordova**: <code>$ sudo npm install -g cordova</code> 
 +  - També ens caldrà **Gradle**: 
 +    - Ajustem [[https://launchpad.net/~cwchien/+archive/ubuntu/gradle|repos ppa]] per tal que s'instal·li la darrera versió:<code>$ sudo add-apt-repository ppa:cwchien/gradle 
 +$ sudo apt install gradle</code> 
 +    - Comprova que és una versió recent (7.x durant l'any 2022) amb:<code>$ gradle -v</code>
  
-Per saber més sobre els entorns virtuals de Python visiteu l'article [[python_venv]].+\\ 
 + 
 +===== Quickstart ====== 
 +La seqüência típica per iniciar un projecte és com s'indica a continuació: 
 +  - Crear projecte: <code>$ cordova create proj1</code> 
 +  - Entrar al directori del projecte: <code>$ cd proj1</code> 
 +  - Afegir plataformes (android/ios/browser): <code>$ cordova platform add android</code> 
 +  - Compilar per Android: <code>$ cordova build android</code> 
 +  - Arrencar el projecte a l'emulador: <code>$ cordova run android</code> 
 + 
 +De vegades no arrenca bé l'emulador. Pots obrir-lo des del Android Studio, però llavors el IDE consumeix força recursos, i complica l'execució. Si tanques el projecte (''File -> Close Project'' a Android Studio) pots  **obrir el AVD Manager** des de la pantalla d'inici d'Android Studio a ''Configure -> AVD Manager''
 + 
 +També pots provar d'**arrencar l'emulador des de la línia de comandes**, com explica la doc oficial https://developer.android.com/studio/run/emulator-commandline 
 +  $ emulator -avd <el_meu_emulador> 
 +Per exemple: 
 +  $ emulator -avd Pixel_2_API_28 
 +   
 +==== Devices ==== 
 +Per córrer l'aplicació sobre un device real només cal que afegiu ''--device'' a la comanda: 
 +  $ cordova run android --device 
 +   
 +Abans, però, caldrà que **configureu el vostre dispositiu en mode developer** buscant les dades del dispositiu i clicant 7 cops seguits al nº de compilació. Després **activeu la Depuració USB**.
  
 \\ \\
  
-===== Creant el primer projecte ===== +===== Troubleshooting =====
-Iniciarem el nostre projecte web creant una simple carpeta:+
  
-    $ mkdir pyweb1 +==== Emulador KVM (Android Studio) ==== 
-    cd pyweb1+Si no et deixa crear una màquina virtual al Android Studio pq li falten permisos d'execució a KVM: 
 +  sudo chmod 777 /dev/kvm
  
-Dins el nostre projecte crearem un virtualenv on posarem les nostres llibreries:+==== Variables d'entorn GNU/Linux ==== 
 +Si al llançar el ''run'' ens dona errors en Ubuntu perquè no troba les llibreries (SDK, JDK), executa: 
 +  export ANDROID_SDK_ROOT=~/Android/Sdk
  
-    $ python -m venv env +El millor és que incloguis aquestes darreres instruccions a l'arxiu ''~/.profile'' del teu //home directory// i així no caldrà picar-les cada cop que vulguis treballar amb Cordova. Si ho fas, per tal de no reiniciar la màquina, pots carregar l'//script// manualment: 
-    $ source env/bin/activate +  source ~/.profile
-    (env) pip3 install flask+
  
-Ara ja podem mirar [[https://flask.palletsprojects.com/quickstart|el quickstart de la documentació de Flask]]. Crearem l'arxiu amb el codi super simple de //Hello World// a l'arxiu ''web.py'': 
  
-    (env) $ gedit web.py &+==== Variables d'entorn Windows ==== 
 +Alguna comanda no et funciona, és perquè necessita estar al PATH per poder ser trobada.
  
-I ara podrem arrencar la aplicació //Hello World// amb:+Cerca "variables" amb el cercador de Windows i t'hauria de facilitar accedir a les variables d'entorn. Modifica la variable PATH per afegir el què et calgui, com per exemple Gradle o el Android SDK que sol estar a: 
 +  \Users\usuari\AppData\Local\Android\Sdk
  
-    (env) $ flask --app web run+Però cerca abans per assegurar-te d'on son exactament les eines.
  
-Podeu visitar la web //Hello World// apuntant el vostre navegador a ''http://localhost:5000''+==== Altres ==== 
 +Si es queixa de: 
 +  No usable Android build tools found. Highest 30.x installed version is 30.0.2; minimum version required is 30.0.3 
 +[[https://stackoverflow.com/questions/70002327/ionic-cordova-android-no-usable-android-build-tools-found-highest-30-x-install|aquest post explica com corregir-ho, simplement seleccionant la versió que necessitem del SDK Manager]]: 
 +  Android Studio -> Tools -> SDK Manager -> Android SDK -> SDK Tools 
 +i **activant ''Show package details''**. 
  
-\\+==== Java version ==== 
 +Si tenim el Java 11 no serveix, ha de ser Java 8. Això ho pots saber amb 
 +  $ java -version
  
-===== Avançant amb Flask =====+Si tenim la 11, podem instal·lar en paral·lel la 8 amb
 +  $ sudo apt install openjdk-8-jdk
  
-==== Routing ==== +I posar la 8 com a versió per defecte amb: 
-Si arribeu a la secció [[https://flask.palletsprojects.com/en/1.1.x/quickstart/#routing|Routing]] entendreu com fer que la nostra aplicació web pugui tenir el què anomenem diversos **punts d'entrada**Ara podem entrar a http://localhost:5000i per http://localhost:5000/hello+  $ sudo update-alternatives --config java 
 +  $ sudo update-alternatives --config javac 
 +   
 +Si es queixa de que no troba JAVA_HOME, l'haurem d'afegir a l'arxiu ''.profile'': 
 +  export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
  
-Com podeu veure a l'exemple, per crear un nou punt d'entrada (accés per una URL) hem de crear una funció (**ULL! no repetir nom de funcions!!**) precedida per un **decorator (app.route)**:+Si aquest no fos el //path// adequat de JAVA_HOME us donaria un errorMireu quin és buscant on està la ruta del compilador java 
 +  $ ll `which javac` 
 +  $ ll /etc/alternatives/javac
  
-<file python web.py> +==== Gradle ==== 
-#... codi previ...+Si es queixa de que li falta //gradle//, l'instal·lem.
  
-@app.route('/hello') +Instal·lar //gradle// per a GNU/Linux: 
-def hello()+  $ sudo add-apt-repository ppa:cwchien/gradle 
-    return 'Hello again!'+  $ sudo apt install gradle
  
-#...mes codi... +Instal·lar //gradle// per a Windows: 
-</file>+  - Descarrega [[https://gradle.org/releases/|la darrera versió de Gradle]] 
 +  - Descomprimeix Gradle a una carpeta tipus C:\Gradle 
 +  - Ajusta la variable d'entorn ''PATH'' per tal que inclogui C:\Gradle\bin
  
-==== Mètodes [GET,POST,+] ==== +Instal·lar //gradle// per MacOS: ...coming soon... probablement brew install gradle
-A més, cal tenir en compte que cada URL la que accedim, ho podem fer amb diferents mètodesA la pràctica ho tractem com si fossin URLs independentsL'exemple típic és el d'un formulari en 2 parts:+
  
-  * GET: és el mètode per defecte, i sol mostrar un formulari estàtic +   
-  * POST: un cop omplert el formulari, processem les dades+I ja pots tornar a provar el ''cordova run android''
  
-Per accedir a les dades que se'ns envia via POSThem d'accedir mitjançant l'[[https://flask.palletsprojects.com/quickstart/#the-request-object|objecte request de la pròpia llibreria de Flask]], tal i com es pot veure en el següent exemple, utilitzant ''request.form['nom']'':+==== Llicències ==== 
 +Si es queixa de que li falten llicències per acceptarentra a ''Android Studio -> SDK Manager'' i accepta les llicències pertinents. També ho pots fer per comandes: 
 +  $ ~/Android/Sdk/tools/bin/sdkmanager --licenses
  
-<file python web.py> +==== Appleios, macos ==== 
-# si no especifiquem res al decoratorés el mètode GET +Treballant amb Apple podem trobar alguns problemes una mica diferents.
-@app.route('/formulari'+
-def formulari_get(): +
-    # mostrem el formulari +
-    return """ +
-<form method='post'> +
-    Introdueix el teu nom: +
-    <input name='nom' type='text' /> +
-    <br> +
-    <input type='submit'> +
-</form> +
-"""+
  
-# important importar la request per accedir a les dades adjuntes +Les variables d'entorn cal ajustar-les d'aquesta manera (en macos Monterey): 
-from flask import request+  export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/ 
 +  export ANDROID_SDK_ROOT=~/Library/Android/sdk
  
-@app.route('/formulari', methods=['POST']+També hi ha un [[https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted|problema amb el nom dels executables del compilador DX]]. Cal renombrar o fer un symlink als arxiu ''d8'' i ''lib/d8.jar'' (en la meva instal·lació estan a ''~/Library/Android/sdk/build-tools/32.0.0-rc1''). 
-def formulari_post()+ 
-    # processem les dades del formulari +[[https://github.com/apache/cordova-ios/issues/407|A la versió Xcode 10 tenim una issue]] que ens fa afegir un paràmetre una mica incòmode a la línia de comandes
-    nom request.form["nom"+  $ cordova build ios --buildFlag='-UseModernBuildSystem=0' 
-    return "Salut, {}".format(nom) +  $ cordova run ios --buildFlag='-UseModernBuildSystem=0' 
-</file>+   
 +Sembla que a partir de Xcode 11 ja no apareix aquest problema. 
 + 
 +Si falla amb el missatge <code>xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance</code> 
 + 
 +[[https://github.com/nodejs/node-gyp/issues/569|Aquest post explica la solució]]: 
 +  $ sudo xcode-select -s /Applications/Xcode-Beta.app/Contents/Developer 
 + 
 +\\ 
 + 
 +====== Construint una App amb JavaScript ====== 
 +Ara que tenim l'entorn preparat, es tracta de desenvolupar una app com si es tractés d'una aplicació web (com si fos pel //browser//amb JavaScript. Podem aplicar llibreries típiques com jQuery o AngularJS, i a més disposarem d'algunes mes per poder accedir al //hardware// del mòbil. 
 + 
 +\\ 
 + 
 +===== Primera App =====
  
-==== Exercici ==== 
 <WRAP todo> <WRAP todo>
-  * Crea un formulari que demani usuari i contrasenya. El formulari s'accedeix per mètode GET però envia les dades per mètode POST. +Mira l'article [[Introducció Javascript]] realitza l'exercici de //login// i registre d'usuaris dins d'una aplicació Cordova.
-  * Crea una pàgina (per POST) que respongui al formulari d'usuari contrasenya. Crea un diccionari global amb noms d'usuari i contrasenyes vàlids (//hardcoded//). +
-  * Assegura't que la pàgina de resposta al formulari respon amb un missatge que contingui un "OK" a la pàgina, si el nom d'usuari és erroni respon adequadament amb un missatge que contingui "ERROR".+
 </WRAP> </WRAP>
  
 \\ \\
  
-===== Variables globals (shhht! q no ho senti ningú!) ===== +===== Afegint jQuery ===== 
-En un entorn web no és recomanable utilitzar variables globals. O més aviat, no podem utilitzar-les com solem fer-ho en aplicacions d'escriptori. Les aplicacions web s'executen en algun servidor web (Apache, Nginx) o servidor d'aplicacions (uwsgi, gunicorn, Heroku).+jQuery ens pot ajudar molt a agilitzar el desenvolupament
  
-De fet, sí que es poden fer servir, però no es pot confiar en què en la següent execució la variable global es mantinguiEl servidor web, depenent de la seva càrrega, pot destruir el procés d'execució de la teva aplicació web, i quan tornes sol·licitar la webes torna posar en marxa tot des de zero (i, per tantdestruint les variables globals).+  - **Instal·lació "a mà"**Cal incloure els arxius de jQuery al nostre projecte. Ho pots fer de diverses maneres: 
 +    - Descarregar els arxius de la web oficial http://jquery.com 
 +    - Utilitzar els repositoris online (CDN). Pots veure com fer-ho en aquest tutorial: 
 +    - https://www.w3schools.com/jquery/jquery_get_started.asp 
 +  - Instal·lació amb el **//package// cordova-jquery de NodeJS** que ens ho facilita (permet posar alguna plantilla típica per apps mòbils). 
 +    - Està força obsoletperò té alguns //templates// que permeten començar ràpid. 
 +    - https://www.npmjs.com/package/cordova-jquery 
 +    - Instal·la-ho l'arrel del teu projecte Cordova:<code>$ npm install cordova-jquery</code> 
 +    - Configura el template. 
 +      * En Linux executa:<code>$ node_modules/cordova-jquery/cordova-jquery</code> 
 +      * En Windows fes des del CMD:<code>node node_modules/cordova-jquery/cordova-jquery</code> 
 +  - Mira com queda la plantilla fent de nou:<code>$ cordova run browser</code>  
 +  - Prova diversos //templates// (per exemple: multipageaccordion, listview). Observa el codi que ens genera per cadascun d'ells, en particular el ''index.html''
 +  - Ens quedarem amb el ''listview'' ja que ens anirà bé com a base per a fer un exercici de //tasklist//
 +    * La [[https://api.jquerymobile.com/listview/|documentació oficial de jQuery movile listview]] ens serà útil per a saber com utilitzar-la.
  
-A més, també hi ha una qüestió de concurrència: el servidor web pot disposar de diferents //threads// o fils d'execució per tal de paral·lelitzar les sol·licituds en diferents CPUs (amb el què aconseguim més capacitat de processament)Si féssim servir variables globals, la informació en diferents instants ens donaria resultats incoherents. +<WRAP important> 
- +Hi ha un petit error a les plantillesQuan arrenquis l'aplicació mira la consola (CTRL+SHIFT+K) i veuràs un error la línia 28 del ''index.js''. Elimina aquesta línia ja que no ens cal i ens atura l'execució de la nostra aplicació. 
-Conclusió: si volem **persistència** en un entorn web, estem obligats utilitzar fitxers o bases de dades.+</WRAP>
  
 \\ \\
  
-===== Utilitzant plantilles (templates) =====+===== Cordova no vol inlines ===== 
 +Típicament podríem fer una aplicació en JavaScript en una pàgina HTML i podríem posar botons que cridin a funcions del nostre codi amb un //onclick// (el què coneixem per crida //inline//). Doncs bé, Cordova no ens deixa fer //inlines//.
  
-Necessitem un mecanisme més sofisticat per crear contingut HTML i que no sigui fent un return d'un string. **Una de les bones pràctiques més transversals a la majoria de //frameworks// és separar nítidament el codi de processament de la renderització HTML**. Per tantno és una bona pràctica posar contingut HTML dins l'arxiu .py en el què estem treballant.+Forma de solventar-ho: fer els botons més senzills, sense //onclick// (però amb //id//): 
 +  <button id="boto1">Prem per afegir</button> 
 +   
 +I desprésen el nostre ''index.js'', ja li afegim el //onclick// (jQuery version): 
 +  $('#addButton').click(addElem);
  
-Per això, separarem les pàgines HTML en les plantilles o //templates// i que renderitzarem des del codi. Per veure un exemple i un resum de les possibilitats que ens ofereixen les plantilles Jinja2podeu mirar-vos aquestes fonts: +En aquest exemple, cridaríem a la funció ''addElem()''.
-  * L'apartat [[https://flask.palletsprojects.com/quickstart/#rendering-templates|"rendering templates" del quickstart de Flask]]. +
-  * La [[https://jinja.palletsprojects.com/templates/|documentació oficial de les plantilles Jinja2]] , que són les que Flask fa servir per defecte.+
  
 +I un darrer apunt, la crida a aquesta funció no pot anar al principi del document, pq en el //head// encara no existeix el nostre //button//. Tenim 2 solucions:
 +  - Posar el tag ''<script src=...'' al final del doc (just després del //button//).
 +  - Posar el codi d'inicialització dins la funció onclick del document, perquè s'executi al acabar de carregar (exemple segueix):<sxh javascript>
 +$(document).ready( function ()  {
 + // initialize
 + $('#addButton').click(addElem);
 + $('#apiButton').click(callAPI);
 +});
 +</sxh>
  
-{{youtube>pv1_CPLg4xw}}+===== Exercici Tasklist v1 =====
  
-==== Exemple carro de compra ==== +<WRAP todo> 
-Com a exemple d'ús de les plantilles agafarem un carro de la compra d'un e-commerceNo serà del tot funcional, ja que ens falta el mecanisme de les sessions per poder gestionar la concurrència al servidor, i distingir entre els diferents clients.+Tasklist
 +  - Inicia un projecte Cordova. 
 +  - Implementa una plantilla amb el [[https://www.npmjs.com/package/cordova-jquery|package NPM cordova-jquery]], tal i com es descriu mes amunt (secció [[#afegint_jquery]]). 
 +    * Es recomana utilitzar la plantilla ''listView''
 +  Implementa el **botó d'afegir tasca**Caldrà que tinguis clar com utilitzar el ''DOM'' amb jQuery: 
 +    * Afegir elements (el text l'agafem d'un //input form// o bé amb un [[https://developer.mozilla.org/es/docs/Web/API/Window/prompt|prompt]]). 
 +    * Tingues en compte la [[https://api.jquerymobile.com/listview/|documentació oficial de la jQuery mobile listview]]. En particular mira el mètode ''refresh()'' que ens aplicarà els estils perquè quan insertem un nou element a la listview quedi amb els estils CSS adequats. 
 +</WRAP>
  
-Farem 2 rutes: +\\
-  * /compra GET : ens mostrarà el formulari. +
-  * /compra POST : processarem les dades enviades al formulari.+
  
-Crea una aplicació mínima com la de l'exemple i afegeix aquestes dues rutes: 
  
-<sxh python> 
-@app.route('/compra') 
-def compra_get(): 
- return render_template('compra_form.html') 
  
-@app.route('/compra',methods=["POST"]) +===== Local Storage ===== 
-def compra_post(): +''localStorage'' és un objecte //built-in// de [[JavaScript]] dintre dels //browsers// que ens permet emmagatzemar dades persistents en una BD interna del tipus //KEY-VALUE//.
- return render_template('compra_post.html'+
-</sxh>+
  
-Com podeu veure, ara ja no creem el HTML dins el codi de l'arxiu '.py' sinó que el posarem en **arxius HTML que cal que estiguin a la carpeta ''/templates''** . Aquests son els arxius compra_form.html i compra_post.html+Les aplicacions web no estaven pensades per emmagatzemar dades, només per ser visualitzades, i en tot cas per interaccionar amb el servidorPer això aquest recurs va trigar en implementar-se en els navegadors. A més, cal tenir en compte que, per raons de seguretat, l'accés al disc dur en un navegador sempre s'ha limitat molt (JavaScript no té accés al //filesystem// per seguretat de les dades de l'usuari).
  
-<file html compra_form.html> +És molt senzill d'utilitzar, al capdavall una DB //key-value// no deixa de ser un diccionari. En principi en tindreu prou amb els mètodes: 
-<form method="post"> +  * localStorage.getItem 
-    <select name="producte"> +  * localStorage.setItem
-        <option>Peres</option> +
-        <option>Pomes</option> +
-        <option>Prunes</option> +
-    </select> +
-    <input type="number" step="0.1" name="quantitat"> +
-    <br> +
-    <input type="submit"> +
-</form> +
-</file>+
  
-<file html compra_post.html> +Mira'la [[https://www.w3schools.com/jsref/prop_win_localstorage.asp|doc de W3Schools]] per aprendre a utilitzar-ho.
-<p>Gràcies per la compra!</p> +
-</file>+
  
-==== Renderitzar dades una plantilla amb {{ ... }} ==== +==== Objectes localStorage ==== 
-Per millorar l'exemple primer de tot personalitzarem el missatge POST on recollim el producte compratEl què voldrem és dir-li a l'usuari quin producte i quantitat han estat afegits al carro:+<WRAP tip> 
 +''localStorage'' només emmagatzema //strings//. Si volem posar objectes complexes, com diccionaris o arrays, caldrà utilitzar algun mètode de serialitzacióLes funcions típiques que s'empren per això son: 
 +  - [[https://www.w3schools.com/js/js_json_stringify.asp|JSON.stringify()]] ens transforma l'objecte en un string per poder ser insertat al ''localStorage''
 +  - [[https://www.w3schools.com/js/js_json_parse.asp|JSON.parse()]] ens permet recuperar un string serialitzat i el restitueix com a objecte. 
 +</WRAP>
  
-<sxh python> +\\
-from flask import request+
  
-@app.route('/compra',methods=["POST"]) 
-def compra_post(): 
-    prod = request.form['producte'] 
-    quant = request.form['quantitat'] 
-    return render_template('compra_post.html', 
-                producte=prod, quantitat=quant) 
-</sxh> 
  
-<file html compra_post.html> +===== Exercici Tasklist v2 ===== 
-<h2>Gràcies per la teva compra!</h2> +Aplicarem tot l'exposat fins aquí en el següent exercici:
-<p>Has comprat {{quantitat}} kg de {{producte}}</p> +
-</file>+
  
-Ara pots provar l'aplicació i veuràs que les dades que s'envien del formulari es mostren a la 2a pàgina. Observa que per passar les dades el què fem és passar-les com a //keyworded arguments// al ''render_template'',els renderitzem amb {{}}+<WRAP todo> 
 +Continua de l'anterior exercici Tasklist v1: 
 +  - Implementa un **botó Elimina** dins de cada element de la llista que esborri aquell element. Convé fer-ho en la pròpia creació de l'element ''jQuery''
 +    * Per saber més [[https://demos.jquerymobile.com/1.4.3/listview/|sobre jQuery UI listview]] 
 +  - Implementa un **botó Edita** dins de cada element de la llista que ens porti a una altra pàgina que ens permeti editar la tasca. 
 +    * Mireu l'exemple inicial on cada element de la llista ens porta una pàgina. En tenim prou amb tenir dues pàgines: la //home// (on hi ha la ''listview''la pàgina //edita//. 
 +  Fes la //tasklist// persistent utilitzant el ''localStorage'', tal com s'explica més amunt. 
 +</WRAP>
  
 +\\
  
-==== Utilitzar codi dins de les plantilles amb {% ... %} ==== 
  
-Pot semblar una contradicció que hi hagi codi dins d'una plantilla, però en realitat és necessari per renderitzar amb facilitat. No és codi de processament, és codi relacionat amb la renderització. Pel nostre cas, es tracta de mostrar els productes que tenim disponibles de forma dinàmica.+===== Utilitzant APIs amb AJAX ===== 
 +Treballar aplicacions en HTML+JS accedir a dades externes és molt còmode utilitzant crides asíncrones amb AJAX.
  
-Per seguirconvé fer-li un cop d'ull la [[http://jinja.pocoo.org/|documentació de les plantilles Jinja2]]. Observa l'exemple que surt: en poques línies ens demostren la majoria de funcions que ens cal per a les plantilles.+Una API webtambé conegut com a //web service// és una interfície via web per demanar dades, així que es podria considerar una crida remota, d'aquí que en diguem API, com les llibreries de programació.
  
-Pel nostre exemple de la botiga, farem una simulació de que disposem d'una llista de productes (en una variable global ''productes'') i l'enviarem a la plantilla per tal que sigui renderitzada en el ''select'' del formulari:+Explorarem la API externa per accedir a dades de www.musicbrainz.org
  
-<sxh python> +Exploreu els següents recursos: 
-productes = ['Cogombres','Pomes','Kiwis']+  - API (respon en XML): https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2 
 +  - Crides en JSON: https://musicbrainz.org/doc/Development/JSON_Web_Service 
 +    * Per obtenir les dades en JSON cal que adjunteu el //header// de curl "Accept:application/json" 
 +  - Per fer //pretty print// d'un JSON va molt bé "empipar-lo" a aquesta comanda:<code>$ curl ... | python3 -m json.tool</code>
  
-@app.route('/compra'+Exemple: 
-def compra_get(): +  $ curl -H 'Accept:application/json http://musicbrainz.org/ws/2/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da | python3 -m json.tool
-    return render_template('compra_form.html', prods=productes) +
-</sxh>+
  
-I renderitzarem la llista de productes en les diferents ''options'' dins la plantilla ''compra_form.html'':+==== AJAX amb jQuery ==== 
 +Aquestes mateixes les podem demanar des d'un document/aplicació HTML+JS amb crides asíncrones, el que solem conèixer per AJAX. Utilitzarem [[http://api.jquery.com/jquery.ajax/|AJAX amb jQuery]] que ens ajudarà a simplificar el codi. Els exemples estan a la mateixa documentació, però us poso aquí un d'essencial per fer la crida i que ens retorni un objecte JSON de la API de musicbrainz.org :
  
-<file html compra_form.html+<code javascript
-<form method="post"> +$.ajax({ 
-    <select name="producte"> +  method"GET", 
-    {for prod in prods %} +  url: "https://musicbrainz.org/ws/2/artist?query=queen"
-        <option>{{prod}}</option> +  dataType: "json",   // necessitem això pq ens retorni un objecte JSON 
-    {% endfor %} +}).done(function (msg) { 
-    </select> +  for(let item in msg.artists) 
-    <input type="number" step="0.1" name="quantitat"> +    console.log(msg.artists[item]); 
-    <br> +    // aquí caldría fer mes coses, of course... 
-    <input type="submit"> +    // ..
-</form> +  }; 
-</file>+}).fail(function () { 
 + alert("ERROR"); 
 +}); 
 +</code>
  
-Comprova que, en efecte funciona la plantilla, canviant la llista de productes i fent-la més llarga.+Cal tenir en compte que les URLs a les que cridis amb AJAX han de tenir habilitada la capçalera de CORS (Cross-Origin Resource Sharing). Les APIs solen tenir-ho habilitat. Totes les APIs públiques ho tenen activat.
  
 +Pots veure una demo i explicació de com funciona a http://ieti.cat/cors/
  
-==== Plantilles like a PRO ==== +[[https://ahorasomos.izertis.com/solidgear/lidiando-con-el-cors/|Aquí s'explica els orígens de CORS]] força correctament.
-Les plantilles Jinja2 ofereixen moltes possibilitats tal i com s'explica a la [[https://jinja.palletsprojects.com/en/2.11.x/templates/|doc oficial de Jinja Templates]]. Destaco els 2 recursos més habituals d'utilitzar, sobretot quan es tracta de tenir una mateixa imatge corporativa en totes les pàgines de l'aplicació:+
  
-  * [[https://jinja.palletsprojects.com/en/2.11.x/templates/#include|Includes]] és una senzilla manera d'afegir capçalera i //footers// iguals totes les nostres pàgines. Us recomano utilitzar això per començar. +<WRAP important> 
-  * [[https://jinja.palletsprojects.com/en/2.11.x/templates/#template-inheritance|Herència de plantilles]] és un mètode una mica més sofisticat amb alguns avantatges, però costa una mica més d'entendre. Cal definir una pàgina //master// dividida en ''blocks'' o seccions, i després derivar les pàgines filles (on podem definir o sobreescriure cada ''block'').+Dins la nostra aplicació cal autoritzar l'accés a les dades externes del domini en qüestióSi no ho fem, ens apareixerà un error a la consola similar a:
  
-\\+<WRAP prewrap> 
 +  Content Security Policy: Els paràmetres de la pàgina han blocat la càrrega d'un recurs a https://musicbrainz.org/ws/2/ («default-src»). 
 +</WRAP>
  
-===== Per a saber-ne més ===== +Per tal d'autoritzar la petició, caldrà que la capçalera META amb la política de seguretat validem la font de dades a l'apartat ''data:'':
-Hem fet un repàs de les funcions bàsiques del //framework// Flask. Ens queda un parell de temes per cobrir tots els temes essencials, i que podeu seguir investigant en el propi [[https://flask.palletsprojects.com/quickstart/|quickstart de Flask]]:+
  
-  * Persistència en base de dades +<WRAP prewrap> 
-  * Sessions+<code html> 
 +<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://fonts.gstatic.com https://code.jquery.com  data: https://musicbrainz.org gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; media-src *; img-src 'self' data: content:;"> 
 +</code> 
 +</WRAP>
  
 +</WRAP>
  
-També hi ha aquest cursos que poden ser interessants: +==== Public APIs a go-go ==== 
-  [[https://courses.miguelgrinberg.com/p/flask-mega-tutorial|mega-tutorial de Flask de Miguel Grinberg]] que té un índex prometedorPodeu fer un cop d'ull a les introduccions, la resta del curs és de pagament+<WRAP tip> 
-  * [[https://platzi.com/cursos/flask/|Aquest curs de Flask de Plazi.com]] pinta molt bé, amb videotutorials en castellà.+[[https://github.com/public-apis/public-apis|En aquest repositori hi ha un llistat de public APIs]] per poder fer aplicacions amb les seves dades. [[https://api.spaceflightnewsapi.net/v3/documentation#/|Mira't la documentació d'aquesta de space news]]. 
 + 
 +Fes-li un cop d'ull i troba el teu //hobby// en una API! 
 +</WRAP> 
 + 
 + 
 +==== Queries a la API de MUSICBRAINZ.COM ==== 
 +Documentació de musicbrainz: 
 +  * [[https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2|Doc oficial API Musicbrainz]]Els exemples ens venen en XML. 
 +  * [[https://musicbrainz.org/doc/Development/JSON_Web_Service|Instruccions per obtenir resultats en format JSON]]
 + 
 +=== Exemples === 
 +Obtenir els resultats (en XML) dels grups amb "queen" al seu nom: 
 +  $ curl https://musicbrainz.org/ws/2/artist?query=queen 
 + 
 +Per obtenir els resultats en format JSON cal afegir un //header// a la //request// de la query, per exemple: 
 +  $ curl https://musicbrainz.org/ws/2/artist?query=queen -H "Accept:application/json" 
 + 
 +Si volem mostrar els resultats de forma mes clara en la //shell//, podem utilitzar una eina per indentar correctament: 
 +  $ curl ...url_query... | python -m json.tool
  
 \\ \\
  
 +===== Materialize CSS =====
 +<WRAP tip>
 +MaterializeCSS és un //framework// CSS per crear interfícies atractives i responsive. Segueix aquest tutorial sobre [[Materialize]] per iniciar un nou projecte amb aquesta eina.
 +</WRAP>
  
-===== Exercici : login ===== 
 <WRAP todo> <WRAP todo>
-Pàgina de login de l'app: +Rock band searcher
- +  Crea un nou projecte Cordova 
-  Crea un formulari que demani usuari i contrasenya. El formulari s'accedeix per mètode GET però envia les dades per mètode POST. +  - Implementa una plantilla amb [[Materialize]]
-  * Crea una pàgina (per POST) que respongui al formulari d'usuari i contrasenya. Crea un diccionari global amb noms d'usuari i contrasenyes vàlids (//hardcoded//)+  - Accedeix a la API de musicbrainz.org i fes una recerca de grups i de cançonstal com s'explica més avall. 
-  * Assegura't que la pàgina de resposta al formulari respon amb un missatge que contingui un "OK" a la pàgina, i si el nom d'usuari és erroni respon adequadament amb un missatge que contingui "ERROR"+    - Primer prova-ho amb ''curl'' 
-  * **Comprova manualment el punt anterior. Abans de fer els tests automàtics cal fer-los manuals PER A TOTS ELS CASOS** (tant si funciona OK, com si dona error).+    - Després implementa-ho en el HTML del projecte Cordova 
 +  - Mostra els resultats de la cerca en una llista HTML
 </WRAP> </WRAP>
  
 \\ \\
  
-===== Testing ===== +===== Plugins ===== 
- +...
-Aquest article continua a [[Python Web Test]].+
  
 \\ \\
 +
 +====== Depuració (debug) ======
 +Per depurar el més fàcil és utilitzar al nostre codi missatges amb
 +  console.log("missatge...")
 +Per poder mostrar aquests missatges dependrà de la plataforma que utilitzem:
 +
 +===== Browser =====
 +Premem F12 per veure el Inspector de Chrome, i anem a la pestanya "Console". També ens serà útil aquesta eina per poder depurar a nivell gràfic i CSS
 +
 +===== Android =====
 +Un cop llançada la app, executem:
 +  $ ./platforms/android/cordova/log
 +
 +Com que surten chorrocientos missatges, és més clar si filtrem només els què ens interessa (tot i que en determinats moments ens pot interessar treure el filtre per veure-ho tot). En aquest cas filtrem amb ''grep'', //case insensitive// (-i), tots els missatges que continguin "console" o "cordova":
 +  $ ./platforms/android/cordova/log | grep -i 'console\|cordova'
 +
 +Potser la manera més còmoda seria posar-ho tot a la mateixa comanda:
 +  $ cordova run android ; ./platforms/android/cordova/log | grep -i 'console\|cordova'
  
playground/prova.txt · Darrera modificació: 2023/06/30 16:56 per isaac_gonzalo_rivero