Web apps


Quoi, comment et autres questions passionantes

Ahmed Kachkach <ahmed.kachkach@gmail.com> - Formation ETIC - INSA de Lyon / Decembre 2013

Avant-propos




. Présentation sur les bases des applications web
. Explications centrées autour d'exemples concrets
. Nous utiliserons Python 2.7


. Téléchargez les exemples de code sur:

Ce que nous allons voir:




. Qu'est ce que le Web?
. Comment communique-t-on dans le Web?
. Comment marche une application Web?
. Quels outils (BdD, frameworks, ...)?

Qu'est ce que le web?

. Le web utilise internet, mais Web != Internet

. Un média accessible pour le développeur et l'utilisateur

. Tout un monde de technologies construit autour du web: Bases de données, serveurs, clients, ... 

. Les technologies du web peuvent aussi être utilisée dans d'autres contextes (ex: FirefoxOS)

Comment ça marche ?


Communication client/serveur



Se fait selon le protocole HTTP, ou HTTPS pour une communication sécurisée.

Ceci signifie que le client et le serveur s'envoient des messages ayant un format précis.

Exemple


 Si vous allez sur http://domain.com/dossier/page.html,
 vous envoyez la requête suivante à domain.com:
GET /dossier/page.html HTTP/1.1
Host: domain.com
User-agent: MonNavigateurSurpuissant/2.17b3
 Et vous recevez une réponse dans ce format:
HTTP/1.1 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Server: Apache/0.8.4
Content-Type: text/html
Content-Length: 59
Expires: Sat, 01 Jan 2000 00:59:59 GMT
Last-modified: Fri, 09 Aug 1996 14:21:40 GMT

<TITLE>Exemple</TITLE>
<P>Ceci est une page d'exemple.</P>

Que fait le serveur?


Plusieurs couches se passent la patate chaude:

Client <-> Serveur <-> Serveur HTTP <-> App

 . Possible d'avoir des couches supplémentaires (cache, load-balancer, pare-feu, etc.)
 . Plusieurs serveurs HTTP connus: Apache, nginx, ...
 . La Web App peut être dans n'importe quel langage: PHP, Python, Ruby , ...

Et le client?


Une fois le code HTML (et les fichiers CSS/JS liés) chargés, il est interprété par le moteur de rendu de votre navigateur (Webkit, Gecko, Lynx, ...).


Paramètres


Des paramètres peuvent aussi être passés lors d'une requête:

. Avec la méthode GET  - arguments inclus dans l'URL

http://domain.com/page.php?arg1=val1&arg2=val2 

. Avec la méthode POSTencodés dans la requête. Utile pour les formulaires, longs arguments, contenu sensible, ...

Créons une application web !


Nous allons commencer à créer une petite web app pour aborder les points suivants:

. Frameworks web
. Bases de données
. Frontend (CSS/JS)

Quel langage?
(vous avez déjà une petite idée...)

PHP
Le plus utilisé par le grand public (wikipedia, facebook, ...)
Simple à déployer (notamment sur du mutualisé)
... Inconsistent, Mal sécurisé. Très verbeux. Pas très fun. 

NodeJS
Javascript côté serveur ! Orienté applications temps-réel.

Ruby
Surtout pour le framework Ruby On Rails

Quel langage?
(oh surprise !)

 Pythooooon !

 (Un peu) plus dur à déployer que PHP.
 Langage simple, rapide... et fun !
 Des milliers et des milliers de librairies.
 Des frameworks webs pour tous les usages: légers ou complexes.
 Utilisé par Reddit, Google (search), YouTube, Blogger, ...

Quel framework?


 Django
 Framework web le plus populaire.
 Inclus une intégration avec les BdD, vérification de formulaires, interface d'administration, ... par défaut !
 Malheureusement trop complexe pour 1 ou 2 heures. 

 Flask
 "Micro-framework" : léger, efficace et expressif !
 Permet de créer des applications (même complexes) de manière très simple.

Hello World avec Flask




from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

1. Routage d'URLS


Le routage des URLs se fait très facilement:

from flask import Flask
app = Flask(__name__)

@app.route("/hello")
def hello():
    return "Hello World!"

@app.route("/profile/<username>") def profile(username): return "You're on the profile {}".format(username) if __name__ == "__main__": app.run()

2. Récupérer les paramètres


Exemple, en GET:
from flask import Flask, request
app = Flask(__name__)

@app.route("/page", methods=["GET"])
def hello():
    if 'name' in request.args:
        return "Hello {}!".format(request.args['name'])
    else:
        return "Missing 'name' argument !"

if __name__ == "__main__":
    app.run()

3. Le debug de la mort qui tue


Faisons planter notre "web app" !

from flask import Flask, request
app = Flask(__name__)

@app.route("/", methods=["GET"])
def hello():
    if 'name' in request.args:
    	big_name = request.args['name'].uppppppppppper()
        return "Hello {}!".format(big_name)
    else:
        return "Missing 'name' argument !"

if __name__ == "__main__":
    app.run(debug=True) 

Passons aux choses sérieuses



En général, le serveur:

1) Extrait des informations de la requête du client
2) Fait des calculs, des requêtes sur la base de donnée, ...
3) Génère une page HTML avec ces données

Templates



La majeure partie des pages que vous voyez est statique, seuls certains éléments changent.

Un template sert donc à représenter les pages HTMLs rendues, et où est inséré le contenu dynamique.

Flask utilise le moteur de templating Jinja2

Exemple d'un template HTML



<html>

	<head>
		<title> Hello ! </title>
	</head>

	<body>
		<ul>
			{% for user in users %}
			<li>{{user['name']}} : {{user['country']}}</li>
			{% endfor %}
		</ul>
	</body>

</html>

Structure d'un projet Flask



 
mon_projet/
    static/
        # images, CSS, JS et autres fichiers statiques
    templates/
        # templates au format Jinja2

    # Nom choisi arbitrairement. Lance votre serveur.
    main.py
 

4. Instantiation du template


 from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
	users_list = []
	users_list.append({'name': 'Adrian', 'country': 'France'})
	users_list.append({'name': 'Loric', 'country': 'France'})
	users_list.append({'name': 'Valentina', 'country': 'Italy'})
	users_list.append({'name': 'Ahmed', 'country': 'Morocco'})

	return render_template('index.html', users=users_list)

if __name__ == "__main__":
    app.run()

Et les données?

Au lieu de "hard-coder" les valeurs: les extraires depuis une base de donnée, facile à mettre à jour.

Plusieurs choix:

Base SQL
MySQL, Postgresql, MariaDB, sqlite, ...

Bases NoSQL
CouchDB, Redis, MongoDB

5. Requêtes MongoDB


Petit aperçu:
import pymongo

# Récupérer/Créer une BdD et une collection
c = pymongo.MongoClient()
db = c["test_db"] # ou c.test_db

# Ajouter des documents à la base de données
db.users.update({"name": "Ahmed", "country": "Morocco"})
db.users.update({....})

# Les récupérer
all_users = db.users.find()
french_users = db.users.find({"country": "France"})

Architecture REST


L'architecture REST organise votre application web en ressources et en méthodes.

Les opérations se font de la manière suivante:
 <GET, POST, DELETE ou PUT> /<ressource>/<id:optionnel>
GET /users/

GET /users/ahmed

POST /users/?name=Valentina&country=Italy

DELETE /users/loric

Le format JSON


Format simple pour transférer des données structurées entre client et serveur.

Même syntaxe que les structures Python et Javascript !

Exemple:
 {"countries": [{"country":"France", "currency":"EUR"}, ...] }

Exemple d'application




Gestion des membres d'un club équestre !
(dossier /poneys/)

Interface REST


@app.route("/users")
def all_users():
	users = list(db.users.find())
	return json.dumps(users)

@app.route("/users/<username>", methods=["GET"])
def get_user(username):
	users = list(db.users.find({"name": username}))
	return json.dumps(users)

@app.route("/users/<username>", methods=["DELETE"])
def delete_user(username):
		db.users.remove({'name': username})
		return json.dumps({'deleted': True})

@app.route("/users", methods=["POST"])
def add_user():
		u_id, username, country = request.form['id'], request.form['name'], request.form['country']
		db.users.insert({'_id': u_id, 'name': username, 'country': country})
		return index()



FIN

Questions?


Web apps et Python

By Ahmed Kachkach

Web apps et Python

  • 2,114