Atelier Django Frontend : interfaces publiques d'un site

Transcriptions des ateliers dispensés par messagerie instantanée dans le cadre de la Semaine tech 2012

Transcription séance du 2012-08-31 02h00 GMT

22h00 heure locale retranscrite ici

[...] historique tronqué suite à rupture connexion...
[...] reprise autour de la partie ORM
(23:56:46) davin.baragiotta: dans le code c'est université
(23:56:47) davin.baragiotta: :
(23:56:56) davin.baragiotta: personnes = Personne.objects.filter(universite__nom__contains='Montréal')
(23:57:00) davin.baragiotta: voilà
(23:57:20) davin.baragiotta: toutes les personnes qui ont une université dont le nom contient "Montréal"
(23:57:21) davin.baragiotta: :D
(23:57:31) davin.baragiotta: ça marche pour tous?
(23:57:33) khone-cc: :-o
(23:57:49) davin.baragiotta: oubliez les reques complexes en SQL!
(23:57:56) davin.baragiotta: *requêtes
(23:58:20) davin.baragiotta: ok, pendant que je fais une pause santé... voici un exercice :
(23:58:35) davin.baragiotta: le code que vous avez préféré, dans le shell... en explorant :
(23:58:45) davin.baragiotta: copiez-le dans la fonction home()
(23:59:12) davin.baragiotta: stockez l'infos que vous aimez dans les variables
(23:59:27) davin.baragiotta: et passez les au template (à travers c = {} )
(23:59:43) davin.baragiotta: il faut au minimum la variable :
(23:59:49) davin.baragiotta: etablissements = Etablissement.objects.all()
(23:59:50) davin.baragiotta: svp ;)
(23:59:57) davin.baragiotta: (de retour dans 2 minutes)
(00:02:10) davin.baragiotta: de retour
(00:10:52) davin.baragiotta: bon retombons sur nos pieds
(00:10:55) davin.baragiotta: on faisait quoi?
(00:11:18) davin.baragiotta: on explorait, dans le shell... l'utilisation de l'ORM pour appeler la DB en Python (pas en SQL)
(00:11:29) davin.baragiotta: pour créer des variables dans home()
(00:11:32) davin.baragiotta: donc
(00:11:45) davin.baragiotta: on va maintenant coder le fruit de nos investigations :
(00:12:31) davin.baragiotta: ajoutez dans home :
(00:12:46) davin.baragiotta: 
    etablissements = Etablissement.objects.all()
    c = {
        'etablissements': etablissements,
    }
(00:12:57) davin.baragiotta: ensuite, dans le template
(00:13:08) davin.baragiotta: au lieu de faire {{ etablissements }}
(00:13:23) davin.baragiotta: je vais vous montrer à boucler avec le langage de templating de Django
(00:13:31) davin.baragiotta: ouvrez home.html
(00:13:39) davin.baragiotta: il existe des "tags"
(00:13:47) davin.baragiotta: qu'on peut utiliser dasn les templates
(00:13:52) davin.baragiotta: voici la doc :
(00:14:16) davin.baragiotta: https://docs.djangoproject.com/en/1.1/
(00:14:20) davin.baragiotta: 1.1
(00:14:31) davin.baragiotta: dans le centre y,a "Templage layer"
(00:14:38) davin.baragiotta: template, désolé
(00:14:51) davin.baragiotta: built-in tags and filters :
(00:14:52) davin.baragiotta: https://docs.djangoproject.com/en/1.1/ref/templates/builtins/#ref-templates-builtins
(00:15:02) davin.baragiotta: filters = un peu comme filtres SPIP
(00:15:10) davin.baragiotta: tag = plus puissant ;)
(00:15:15) davin.baragiotta: tag for
(00:15:25) davin.baragiotta: https://docs.djangoproject.com/en/1.1/ref/templates/builtins/#for
(00:15:38) davin.baragiotta: {% for e in etablissements %}
(00:15:48) davin.baragiotta: ça ressemble beaucoup à Python
(00:15:52) davin.baragiotta: mais c'en est pas
(00:16:01) davin.baragiotta: faut finir tout tag
(00:16:06) davin.baragiotta: avec son endtag
(00:16:12) davin.baragiotta: {% endfor %}
(00:16:24) davin.baragiotta: codez ceci dans votre template, pour le plaisir :
(00:17:35) khone-cc: <h2>Classe Etablisement</h2>
{% for e in etablissements %}
<li>{{ e }}</li>
{% endfor %}
(00:17:43) davin.baragiotta: ahaha oui!
(00:17:57) davin.baragiotta: (je fatigue! ;) )
(00:18:06) davin.baragiotta: 
<h2>Classe Etablisement</h2>
{% for e in etablissements %}
<li>{{ e }}</li>
{% endfor %}
(00:18:11) davin.baragiotta: mieux
(00:18:25) davin.baragiotta: ajoutez <ul> et </ul>
(00:18:29) davin.baragiotta: avant et après for
(00:18:34) davin.baragiotta: pour faire du vrai HTML ;)
(00:18:39) khone-cc: ok
(00:18:48) davin.baragiotta: ok, vous voyez la liste des établissements?
(00:19:25) davin.baragiotta: maintenant... malheureusement l,atelier tire à sa fin
(00:19:31) davin.baragiotta: on est déja`en retard
(00:19:37) davin.baragiotta:  mais moi j'ai un peu de temps
(00:19:40) khone-cc: moi, ça à l'aire bien affiché ..
(00:19:46) davin.baragiotta: au mois pour conclure ;)
(00:20:03) davin.baragiotta: revenons au plan :
(00:20:15) davin.baragiotta: ORM : utilisation réelle
(00:20:23) davin.baragiotta: on est rendu dans l'utilisation réelle de l'ORM
(00:20:26) davin.baragiotta: c'est fait
(00:20:35) davin.baragiotta: rendez-vous compte des possibilités :
(00:20:55) davin.baragiotta: vous appelez les données de la base de données comme vous voulez, pour créer une page HTML
(00:21:02) davin.baragiotta: ça pourrait être du RSS
(00:21:21) davin.baragiotta: appeller la DB pour lister dans un template respectant syntaxe RSS les nouvelles
(00:21:30) davin.baragiotta: (mais y,a des outils qui font ça automatiquement)
(00:21:44) davin.baragiotta: je voulais vous faire coder d'autres trucs
(00:21:50) davin.baragiotta: mais tout est toujours trop long
(00:21:57) davin.baragiotta: je vous propose donc de vous téléporter
(00:21:59) davin.baragiotta: dans le temps
(00:22:07) davin.baragiotta: en téléchargeant les sources finales de l'atelier
(00:22:16) davin.baragiotta: avec plein truc dont je peux parler en démo
(00:22:22) davin.baragiotta: (fini le code pour vous)
(00:22:25) davin.baragiotta: ça vous va?
(00:22:45) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support?action=AttachFile&do=get&target=carto_1_1_final.tar.gz
(00:22:52) davin.baragiotta: sources finales
(00:23:08) davin.baragiotta: décompresser + aller dans répertoire
(00:23:16) davin.baragiotta: + python manage.py runserver
(00:24:23) davin.baragiotta: tout le monde y est?
(00:33:11) davin.baragiotta: messieurs... l'heure est grave....
(00:33:21) davin.baragiotta: c'est la finale en feu d'artifice
(00:33:31) davin.baragiotta: vous avez téléchargé les sources finales
(00:33:43) davin.baragiotta: vous avez décompressé le .tar.gz
(00:33:58) davin.baragiotta: vous êtes dans le répertoire du projet décompressé
(00:34:08) davin.baragiotta: vous allumez le feu :
python manage.py runserver
(00:34:12) davin.baragiotta: et allez sur :
(00:34:22) davin.baragiotta: http://127.0.0.1:8000
(00:34:27) davin.baragiotta: tadaaaaaaaaaaaaaaaaaaaaaaaaaam!!!!!!
(00:35:12) davin.baragiotta: vous devriez avoir un super site avec des styles
(00:35:15) davin.baragiotta: entre autres
(00:35:26) davin.baragiotta: ça marche? (mais cachez votre joie!)
(00:36:59) davin.baragiotta: bon je termine en vous montrant ce qui a été fait... que vous n'avez pas fait :
(00:37:07) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(00:37:13) davin.baragiotta: héritage de template
(00:37:20) davin.baragiotta: regardez bien... y,a un base.html
(00:37:30) davin.baragiotta: qui déclare des {% block ...
(00:37:37) davin.baragiotta: et toutes les autres pages
(00:37:47) davin.baragiotta: {% extends "base.html"
(00:38:01) davin.baragiotta: de sorte que tout le vrai code HTML qu'on veut pas coder dans chaque page
(00:38:05) davin.baragiotta: est dans base.html
(00:38:14) davin.baragiotta: et les autres pages remplissent les block
(00:38:18) davin.baragiotta: autre chose
(00:38:27) davin.baragiotta: les URLs avec paramètres
(00:38:36) davin.baragiotta: ouvres annuaire/urls.py
(00:38:47) davin.baragiotta: voyez la syntaxe particulière pour capter l'id
(00:39:00) davin.baragiotta: ouvrez annuaire/views.py
(00:39:28) davin.baragiotta: regardez le id passé à la fonction... qui nous permet de faire un .get() dans l'ORM... comme on a fait dans le shell
(00:39:47) davin.baragiotta: avec ça : on fait une page de détail... pour CET établissement ou CETTE personne
(00:40:06) davin.baragiotta: le plus impressionnant, c'est le style
(00:40:15) davin.baragiotta: mais c'est rien d'autre que du CSS
(00:40:23) davin.baragiotta: dans répertoire /media/
(00:40:31) davin.baragiotta: correctemetn configuré dans settings.py
(00:40:45) davin.baragiotta: et utilisé dans base.html : {{ MEDIA_URL }}
(00:40:59) davin.baragiotta: finalement...
(00:41:03) davin.baragiotta: la connexion du user
(00:41:15) davin.baragiotta: que je vous laisse expérimenter dans les interfaces
(00:41:30) davin.baragiotta: et étudier sur : urls.py, connexion.html, deconnexion.html
(00:41:38) davin.baragiotta: voilà, c'est tout?
(00:41:56) davin.baragiotta: (24 minutes de dépassé)
(00:41:59) davin.baragiotta: des questions?
(00:42:58) davin.baragiotta: si pas de question... je conclue
(00:43:36) khone-cc: (11:43:37) khuon.tiv: Combien de web codes ont dans cet interface ? Python-Django CSS HTML quoi d'autre ?
(00:44:41) davin.baragiotta: web codes? pas sûr de comprendre... mais les technos impliqués :
(00:45:08) davin.baragiotta: oui : python, django (framework Python), Apache éventuellement, HTTP, CSS, HTML, JS au besoin
(00:45:11) davin.baragiotta: voir le schéma :
(00:45:19) davin.baragiotta: http://montrealpython.org/r/attachments/13/web-development.jpg
(00:45:28) davin.baragiotta: autres questions?
(00:45:43) khone-cc: Non
(00:45:46) khone-cc: yeap, GRAND MERCI PROF PYTHON-DJANGO...
(00:46:02) davin.baragiotta: :D
(00:46:04) khone-cc: on lui laisse à Dodo...
(00:46:09) davin.baragiotta: je conclue donc rapido :
(00:46:16) davin.baragiotta: vous avex une bombe entre les mains :
(00:46:23) davin.baragiotta: la puissance de Python sur le web
(00:46:40) davin.baragiotta: tout ce que vous êtes capables de faire avec des import de Python...
(00:46:52) davin.baragiotta: ... vous pouvez l'utiliser sur le web avec les views...
(00:47:00) davin.baragiotta: et stocker vos data dans une DB
(00:47:24) davin.baragiotta: (là c'était sqlite... mais on peut mettre MySQL évidemment, ou autre)
(00:47:36) davin.baragiotta: tous nos projets SI de l'AUF = Django
(00:47:45) davin.baragiotta: y,a du Python partant dans git.auf.org!
(00:48:00) davin.baragiotta: je vous laisse apprécier la montée en puissance que vous venez de faire
(00:48:02) davin.baragiotta: et surtout
(00:48:13) davin.baragiotta: on est tous ensemble, tout le temps... la communauté tech :
(00:48:22) davin.baragiotta: on vit dans le salon tech, ari-si ou autres
(00:48:32) shafeek.sumser: davin une dernière question: est-ce qu'avec django on peut faire du ajax et jquery?
(00:48:33) davin.baragiotta: n'hésitez à poser les questions et...
(00:48:59) davin.baragiotta: ... on n'est pas obligés d,attendre la prochaine semaine Tech pour continuer d'apprendre et collaborer ;)
(00:49:02) davin.baragiotta: réponse :
(00:49:19) davin.baragiotta: oui, Ajax = rien d'autre qu'un appel de JS sur serveur...
(00:49:39) davin.baragiotta: un appel partiel, en quelque sorte car veut pas une page complète
(00:49:40) davin.baragiotta: donc
(00:49:55) davin.baragiotta: on met le code JQuery qu'on veut dans notre template HTML
(00:50:39) davin.baragiotta: dans une balise link qui lie vers un script : dans /media/js ( {{ MEDIA_URL }}/js/le_script_qui_tue.js
(00:50:45) davin.baragiotta: ensuite
(00:50:50) davin.baragiotta: ce script appelle une URL
(00:50:55) davin.baragiotta: gérée dans urls.py
(00:51:05) davin.baragiotta: qui appelle une fonction dans views.py
(00:51:14) davin.baragiotta: qui retourne un FRAGMENT HTML
(00:51:22) davin.baragiotta: même principe qu'on vient de voir
(00:51:34) davin.baragiotta: sauf un appel partiel pour raffraichir un fragmenr de code
(00:51:51) davin.baragiotta: le JS dans jQuery qui reçoit la réponse partielle...
(00:52:00) davin.baragiotta: ... va ajouter ce fragment dans le DOM en cours
(00:52:03) shafeek.sumser: ok j'étais pas présent, viens d'arriver au bureau je rattraperai ce soir
(00:52:06) davin.baragiotta: voilà ;)
(00:52:22) davin.baragiotta: ok à ce soir (ce matin pour moi... en fait ;) )
(00:52:39) davin.baragiotta: ---------------------- FIN ATELIER DJANGO FRONTEND --------------------------------

Transcription séance du 2012-08-31 15h00 GMT

11h00 heure locale retranscrite ici

(11:30:40) davin.baragiotta: --------- ATELIER DJANGO : Frontend : interfaces publiques ---------------
(11:30:50) davin.baragiotta: Le plan de l,atelier est ici :
(11:31:01) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(11:31:06) davin.baragiotta: INTRODUCTION
(11:31:27) davin.baragiotta: si des personnes n'ont pas suivi l'atelier Backend (pas obligatoire)
(11:31:39) davin.baragiotta: le dire dans tehc à modératuer niry.andriambelo svp
(11:31:40) davin.baragiotta: tech
(11:31:42) davin.baragiotta: ok
(11:31:46) davin.baragiotta: notre objectif maintenant
(11:32:04) davin.baragiotta: c'est de créer des interfaces web (HTML) d'affichage de nos données
(11:32:10) davin.baragiotta: non, ce n'est pas un atelier HTML
(11:32:36) davin.baragiotta: je suppose que tout le monde a Django 1.1.1
(11:32:43) davin.baragiotta: RAPPELS
(11:33:00) davin.baragiotta: reprenons le schéma sur le développement web
(11:33:07) davin.baragiotta: http://montrealpython.org/r/attachments/13/web-development.jpg
(11:33:26) davin.baragiotta: on a vu urls.py (un peu...)
(11:33:29) davin.baragiotta: models.py
(11:33:31) davin.baragiotta: et admin.py
(11:33:46) davin.baragiotta: maintenant, on va travailler dans urls.py, views.py et template
(11:34:10) davin.baragiotta: en gros... l,admin fournit des interfaces toutes faites pour gestion habituelle....
(11:34:21) davin.baragiotta: là on va faire les interfaces à la main... créer notre site quoi!
(11:34:38) davin.baragiotta: pour pouvoir afficher nos données
(11:34:47) davin.baragiotta: en fait, pour simplifier l'atelier
(11:34:59) davin.baragiotta: je propose que nous partions tous du même code
(11:35:02) davin.baragiotta: avec les mêmes données
(11:35:05) davin.baragiotta: ce sera plus simple
(11:35:15) davin.baragiotta: téléchargez l'archive :
(11:35:20) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support%3Faction%3DAttachFile%26do%3Dget%26target%3Dcarto_1_1_backend_final.tar.gz
(11:35:27) davin.baragiotta: décompressez
(11:35:36) davin.baragiotta: grrrr
(11:35:48) davin.baragiotta: je hais les pièces jointes de moinmoin
(11:35:59) davin.baragiotta: minute
(11:36:19) davin.baragiotta: http://git.auf.org/?p=davin.git;a=commit;h=c0c1a067233e527f80c08b4f9d2fd84db5ca5269
(11:36:29) davin.baragiotta: mes sources sur mon dépôt git perso...
(11:36:31) davin.baragiotta: davin.git
(11:36:47) davin.baragiotta: sur ce lien, cliquer sur "snapshot"
(11:36:53) davin.baragiotta: http://git.auf.org/?p=davin.git;a=snapshot;h=c0c1a067233e527f80c08b4f9d2fd84db5ca5269;sf=tgz
(11:37:09) davin.baragiotta: vous avez TOUT mon dépôt personnel...
(11:37:13) davin.baragiotta: ce qui nous intéresse
(11:37:20) davin.baragiotta: (après décompression)
(11:37:23) davin.baragiotta: c'est ici :
(11:37:52) davin.baragiotta: davin-c0c1a06/ateliers/django/carto_1_1
(11:38:04) davin.baragiotta: copier ce répertoire à côté de votre carto, si vous voulez
(11:38:23) davin.baragiotta: voilà...
(11:38:50) davin.baragiotta: on va voir ce que ce projet... qui correspond au code complet de l,atelier Backend (même les trucs pas couverts)
(11:38:54) davin.baragiotta: avec un bon jeu de données
(11:38:59) davin.baragiotta: cd carto_1_1
(11:39:06) davin.baragiotta: 
python manage.py runserver
(11:39:56) davin.baragiotta: vous devriez pouvoir accéder à l'admin :
(11:40:09) davin.baragiotta: admin/admin
(11:40:21) davin.baragiotta: regardez les données
(11:40:30) davin.baragiotta: y,a 11 établissemetns
(11:40:38) davin.baragiotta: 24 personnes
(11:40:42) davin.baragiotta: ok pour tous?
(11:40:44) davin.baragiotta: des questions?
(11:40:56) niry.andriambelo: non
(11:41:21) niry.andriambelo: on suppose que oui, personne ne dit le contraire
(11:41:22) davin.baragiotta: ok super... on a donc tous les mêmes données à afficher dans nos pages
(11:41:30) davin.baragiotta: qui ne dit mot, consent ;)
(11:41:47) davin.baragiotta: je crois que la première étape... c'est de se créer une page d'accueil :D
(11:41:58) davin.baragiotta: tapez :
(11:42:06) davin.baragiotta: http://127.0.0.1:8000/
(11:42:12) davin.baragiotta: 404...
(11:42:14) davin.baragiotta: c'est nul
(11:42:20) davin.baragiotta: on n'a pas de page d'accueil
(11:42:35) davin.baragiotta: première étape = ? point d'entrée = ?
(11:42:38) davin.baragiotta: urls.py
(11:43:03) davin.baragiotta: 
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    # Example:
    # (r'^carto/', include('carto.foo.urls')),
    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
)
(11:43:19) davin.baragiotta: bon on se rappelle que urls.py = les règles... patterns d'URL gérées
(11:43:25) davin.baragiotta: on n'a que admin/
(11:43:28) davin.baragiotta: on va créer /
(11:43:51) davin.baragiotta: je vous donne le code
(11:43:53) davin.baragiotta: et on en parle
(11:44:12) davin.baragiotta: 
url(r'^$', 'carto_1_1.views.home', name='home'),
(11:44:23) davin.baragiotta: 
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    url(r'^$', 'carto_1_1.views.home', name='home'),
    # Example:
    # (r'^carto/', include('carto.foo.urls')),
    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
)
(11:44:36) davin.baragiotta: lisons
(11:44:57) davin.baragiotta: (attention... le projet s'appelle carto_1_1... pas carto... oui je sais c'est laid)
(11:45:15) davin.baragiotta: j'ai ajouté une nouvelle règle
(11:45:22) davin.baragiotta: avec fonction url()
(11:45:37) davin.baragiotta: qui elle, on le voit pas, mais est importée avec le * de 
from django.conf.urls.defaults import *
(11:45:47) davin.baragiotta: url() prend 3 params :
(11:46:21) davin.baragiotta: 1. le pattern qui doit matcher (un pattern de regex, regular expression... voir module re de standard library)
(11:46:46) davin.baragiotta: 2. la vue qui doit être exécutée pour créer la réponse à la requête
(11:46:58) davin.baragiotta: 3. un nom, par commodité, pour faire référence à cette règle
(11:47:00) davin.baragiotta: donc
(11:47:03) davin.baragiotta: lisons :
(11:47:08) davin.baragiotta: url(r'^$', 'carto_1_1.views.home', name='home'),
(11:47:42) davin.baragiotta: l'URL qui commence (^) avec et qui finit avec ($) rien...
(11:48:15) davin.baragiotta: ... sera traitée par la fonction home() dans le fichier views.py du projet carto_1_1...
(11:48:30) davin.baragiotta: (par ailleurs cette règle s'appelle "home")
(11:48:41) davin.baragiotta: commence et finit avec rien...
(11:48:54) davin.baragiotta: entre ^ et $... ben il n'y a pas de caractère dans le pattern
(11:49:16) davin.baragiotta: donc strictement... ça veut dire : si j'appelle mon URL juset avec le nom de domaine... sans rien derrière, ça amtche
(11:49:26) davin.baragiotta: c'est donc notre root, notre page d'accueuil
(11:49:30) davin.baragiotta: super, on teste!!!!!
(11:49:47) davin.baragiotta: 
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    url(r'^$', 'carto_1_1.views.home', name='home'),
    # Example:
    # (r'^carto/', include('carto.foo.urls')),
    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
)
(11:49:52) davin.baragiotta: + sauvegarde ;)
(11:49:59) davin.baragiotta: http://127.0.0.1:8000/
(11:50:39) davin.baragiotta: hmmm... je m'attendais à une erreur... pas au 404 :(
(11:50:56) davin.baragiotta: ahaha, je suis pas dans le bon projet! ;)
(11:51:15) davin.baragiotta: (j'étais encore dans carto... faut être dans carto_1_1)
(11:51:36) davin.baragiotta: hourra! erreur!
(11:51:41) davin.baragiotta: ViewDoesNotExist at /
(11:51:48) davin.baragiotta: Could not import carto_1_1.views. Error was: No module named views
(11:52:12) davin.baragiotta: ouaip... en effet... le fichier views.py n'existe pas
(11:52:18) davin.baragiotta: on va le créer à la racine du projet
(11:52:34) davin.baragiotta: ah... vous pourriez dire "oui mais il existe dans annuaire/views.py"
(11:53:00) davin.baragiotta: la page d'accueil... est indépendante des apps... c'est un choix de design que j'impose ;)
(11:53:22) davin.baragiotta: donc je veux pas que ce soit dans un app particulièrement, mais à la racine du projet, pour la page d'accueil
(11:53:33) davin.baragiotta: alors créons : carto_1_1/views.py
(11:53:57) davin.baragiotta: je vous donne le code de base et on discute
(11:54:07) davin.baragiotta: on veut créer la focntion home()
(11:54:46) davin.baragiotta: le code est dans la page de l,atelier :
(11:54:51) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(11:55:04) davin.baragiotta: django 1.1.1
(11:55:05) davin.baragiotta: 
from django.shortcuts import render_to_response from django.template import Context, RequestContext  def home(request):     c = {}     return render_to_response("home.html", Context(c), context_instance = RequestContext(request))
(11:55:08) davin.baragiotta: grrr...
(11:55:15) davin.baragiotta: 
from django.shortcuts import render_to_response
from django.template import Context, RequestContext
def home(request):
    c = {}
    return render_to_response("home.html", Context(c), context_instance = RequestContext(request))
(11:55:23) davin.baragiotta: ok lisons
(11:55:31) davin.baragiotta: premières lignes... des imports...
(11:55:40) davin.baragiotta: faut juste vérifier que ce qui est importé est utilisé
(11:55:58) davin.baragiotta: render_to_response, Context, RequestContext... ok tout est utilisé plus bas
(11:56:08) davin.baragiotta: def home():
(11:56:16) davin.baragiotta: def = pour créer fonction en Python
(11:56:25) davin.baragiotta: home = nom de la fonction
(11:56:39) davin.baragiotta: entre les parenthèses... les paramètres
(11:56:56) davin.baragiotta: request : aaaaaah.... input = requête et output = réponse?
(11:57:02) davin.baragiotta: oui
(11:57:16) davin.baragiotta: l'output d'une fonction... c'est ce qu'elle retourne :
(11:57:23) davin.baragiotta: return render_to_response()
(11:57:41) davin.baragiotta: on utilise une fonction pour "rendre en réponse"
(11:57:53) davin.baragiotta: ce qu'on va "rendre"... c'est un template HTML
(11:57:59) davin.baragiotta: ici, c'est home.html
(11:58:29) davin.baragiotta: les autres params de render_to_responses... sont du contexte que l'on passe au template...
(11:58:43) davin.baragiotta: ... pour qu'il ait des variables (on y reviwent)
(11:58:48) davin.baragiotta: ok testons
(11:58:49) davin.baragiotta: :D
(11:58:59) davin.baragiotta: refresh : http://127.0.0.1:8000/
(11:59:09) davin.baragiotta: hourra! une autre erreur!
(11:59:10) davin.baragiotta: ;)
(11:59:21) davin.baragiotta: (ça veut dire qu'on a réglé la première ;) )
(11:59:26) davin.baragiotta: TemplateDoesNotExist at /
(11:59:30) davin.baragiotta: home.html
(11:59:33) davin.baragiotta: mouaip...
(11:59:50) davin.baragiotta: c'est vrai qu'on n,a pas créé encore le template home.html demandé par /
(11:59:55) davin.baragiotta: on le fait? on est rendu là ;)
(12:00:11) davin.baragiotta: ok, encore un peu de config dans notre jeune projet
(12:00:24) davin.baragiotta: créons un répertoire "templates" à la racine du projet
(12:00:41) davin.baragiotta: templates... c'est le nom par convention
(12:00:55) davin.baragiotta: on va créer dedans, le fichier home.html
(12:01:26) davin.baragiotta: dans home.html... on mettre du contenu bien... genre :
<h1>Bonjour AUF</h1>
(12:01:56) davin.baragiotta: pour ceux moins à l,aise avec HTML... pas de probl.. rien de compliqué ici
(12:02:03) davin.baragiotta: refresh?
(12:02:10) davin.baragiotta: TemplateDoesNotExist at /
(12:02:11) davin.baragiotta: pareil
(12:02:24) davin.baragiotta: en fait, faut configurer dans settings.py où se trouvent les templates
(12:02:34) davin.baragiotta: settings.py TEMPLATE_DIRS
(12:02:47) davin.baragiotta: 
TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)
(12:02:50) davin.baragiotta: lisons.,..
(12:03:08) davin.baragiotta: absolute paths... mouais....
(12:03:17) davin.baragiotta: mais quand je vais déployer mon code sur serveur
(12:03:37) davin.baragiotta: j'ai pas envie de venir modifier ce settings... (on pourrait mais c'est nul)
(12:04:02) davin.baragiotta: on va donc créer dynamiquement, en Python, le chemin absolu.... et on va le faire à partir de l'emplacement de settings.py
(12:04:11) davin.baragiotta: en haut, dans settings.py
(12:04:14) davin.baragiotta: import os
(12:04:29) davin.baragiotta: os : c'est un module de la standard library
(12:04:39) davin.baragiotta: sert à manipuler syst de fichiers, notamment
(12:04:42) davin.baragiotta: puissant ;)
(12:04:49) davin.baragiotta: ensuite, ajouter :
(12:05:02) davin.baragiotta: modifier TEMPLATE_DIRS
(12:05:25) davin.baragiotta: TEMPLATE_DIRS = (
    os.path.join(os.path.dirname(__file__), "templates"),
)
(12:05:28) davin.baragiotta: 
TEMPLATE_DIRS = (
    os.path.join(os.path.dirname(__file__), "templates"),
)
(12:05:34) davin.baragiotta: voila... lisons....
(12:06:10) davin.baragiotta: __file__ = variable représentation le fichier en cours d'exécution... settings.py dans le contexte...
(12:06:31) davin.baragiotta: .dirname() va chercher tout le path absolu de settings.py
(12:07:02) davin.baragiotta: .join() joint le path absolu de settings path au string final "templates"
(12:07:35) davin.baragiotta: donc répertoire templates, se trouve absolument à côté de settings.py
(12:07:38) davin.baragiotta: vouala
(12:07:41) davin.baragiotta: refresh????
(12:08:16) davin.baragiotta: Bonjour AUF
(12:08:18) davin.baragiotta: :D
(12:08:24) davin.baragiotta: ça marche pour tous?
(12:08:29) davin.baragiotta: questions?
(12:08:51) niry.andriambelo: darko.stanar: NameError: name 'os' is not defined
(12:09:20) davin.baragiotta: faut pas oublier d'importer ce qu'on utilise :
(12:09:25) davin.baragiotta: en haute de fichier :
import os
(12:09:39) davin.baragiotta: permet de faire :
os.path....
(12:09:45) davin.baragiotta: ok?
(12:10:04) niry.andriambelo: pas d'autres remarques donc ok
(12:10:08) davin.baragiotta: super...
(12:10:13) davin.baragiotta: on a fait quoi?
(12:10:19) davin.baragiotta: modifié urls.py
(12:10:34) davin.baragiotta: créé home() pour / dans views.py
(12:10:43) davin.baragiotta: et créé le templates (+ config)
(12:10:58) davin.baragiotta: on vient de faire le chainage complet du frontend
(12:11:05) davin.baragiotta: mais
(12:11:07) davin.baragiotta: c'est nul
(12:11:17) davin.baragiotta: car bonjour AUF... c'est une page statique
(12:11:24) davin.baragiotta: on veut afficher une variable
(12:11:34) davin.baragiotta: on va donc créer une variable dans home()
(12:11:39) davin.baragiotta: et la passer au template ;)
(12:11:43) davin.baragiotta: views.py :
(12:11:56) davin.baragiotta: codons une variable bidon :
(12:12:02) davin.baragiotta: variable = "Davin"
(12:12:22) davin.baragiotta: attention à indentation
(12:12:35) davin.baragiotta: doit être aligné avec c = {}.... sous def
(12:12:43) davin.baragiotta: pour la passer au template....
(12:12:57) davin.baragiotta: on va stocker toutes les variables dans le dictionnaire c
(12:13:11) davin.baragiotta: on voit que c = dictionnaire car utilise {}
(12:13:30) davin.baragiotta: rappel : un dictionnaire est un ensemble de clé-valeur
(12:13:39) davin.baragiotta: on va donc créer une clé : 'var'
(12:13:49) davin.baragiotta: il donner la valeur de notre variable :
(12:14:16) davin.baragiotta: 
from django.shortcuts import render_to_response
from django.template import Context, RequestContext
def home(request):
    variable = "Davin"
    c = {
        'var':variable,
    }
    return render_to_response("home.html", Context(c), context_instance = RequestContext(request))
(12:14:36) davin.baragiotta: 'var' sera le nom de la variable dans le template...
(12:14:49) davin.baragiotta: essayons maintenant d'afficher cette variable dans le template
(12:14:57) davin.baragiotta: templates/home.html :
(12:15:10) davin.baragiotta: ajoutez {{ var }}
(12:15:28) davin.baragiotta: 
<h1>Bonjour AUF</h1>
{{ var }}
(12:15:49) davin.baragiotta: attention : on n,est plus dans du Python.... on est dans le langage de template de Django
(12:16:12) davin.baragiotta: il existe, dans l'univers Python, d'autres moteur de template... avec leur propre syntaxe (ex.: mako)
(12:16:26) davin.baragiotta: mais Django est monolithique : il utilise son propre moteur...
(12:16:38) davin.baragiotta: la doc des conventions syntaxiques esst donc dans la doc de Django :
(12:16:46) davin.baragiotta: https://docs.djangoproject.com/en/1.1//
(12:16:52) davin.baragiotta: sous Template layer :
(12:17:21) davin.baragiotta: Syntax overview et Built-in tags and filters = l'important pour nous
(12:17:23) davin.baragiotta: on y revient
(12:17:24) davin.baragiotta: donc
(12:17:27) davin.baragiotta: {{ }}
(12:17:38) davin.baragiotta: c'est la syntaxe pour afficher une variable
(12:17:41) davin.baragiotta: ok, refresh
(12:18:09) davin.baragiotta: si vous voyez rien, relisez et corrigez code... et n'oubliez pas de sauvegarder
(12:18:11) davin.baragiotta: ;)
(12:18:19) davin.baragiotta: cool... je vois ceci :
(12:18:24) davin.baragiotta: 
Bonjour AUF  Davin 
(12:18:42) davin.baragiotta: on sait maintenant passer une variable aux templates! :D
(12:18:44) davin.baragiotta: questions?
(12:19:02) niry.andriambelo: à priori c'est ok
(12:19:05) davin.baragiotta: super
(12:19:20) davin.baragiotta: mais ça reste un peu nul notre truc...
(12:19:23) davin.baragiotta: pourquoi?
(12:19:40) davin.baragiotta: ben ma variable est "codée en dur" (hardcodée) dans ma fonction
(12:19:50) davin.baragiotta: ce template affichera toujours "Davin"
(12:20:01) davin.baragiotta: c'est comme si je l'avait écrit direct dans le template... non?
(12:20:09) davin.baragiotta: ce qu'on veut, c'est du contenu dynamique :
(12:20:27) davin.baragiotta: que le contenu s'affiche en appelant la base de données :
(12:20:48) davin.baragiotta: dynamique dans le sens où le contenu de la page change si le contenu de la DB change
(12:21:02) davin.baragiotta: listons nos établissements sur la page d'accueil!!! :D
(12:21:13) davin.baragiotta: hmmm... comment faire?
(12:21:31) davin.baragiotta: c'est là que la notion d'ORM entre en ligne de compte
(12:21:36) davin.baragiotta: plan de match :
(12:21:42) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(12:21:46) davin.baragiotta: je suis ici :
(12:21:52) davin.baragiotta: ORM : exploration interactive
(12:22:13) davin.baragiotta: ORM veut dire "object relational mapping"
(12:22:15) davin.baragiotta: en fr :
(12:22:32) davin.baragiotta: association des objets aux tables relationnelles de la DB
(12:23:02) davin.baragiotta: les objets... sont définis dans les models.py
(12:23:10) davin.baragiotta: ce sont nos Etablissement et Personne
(12:23:33) davin.baragiotta: on sait qu'ils existent dans la DB... ils ont leurs tables créées avec syncdb
(12:23:34) davin.baragiotta: mais
(12:23:40) davin.baragiotta: on ne veut PAS faire du SQL
(12:23:47) davin.baragiotta: on est des développeurs Python ;)
(12:23:57) davin.baragiotta: on veut accéder aux données, sans coder de SQL
(12:24:03) davin.baragiotta: l'IORM sert à ça :
(12:24:11) davin.baragiotta: accéder à la DB en codant en Python
(12:24:23) davin.baragiotta: l'ORM fonctionne, car nos classes, dans models.py
(12:24:43) davin.baragiotta: ont hérité de models.Model.... : ce modèle parent, fournit la mécanique nécessaire pour appeler la DB
(12:24:48) davin.baragiotta: testons!
(12:25:22) davin.baragiotta: pour tester, on va faire comme dans l'atelier Python : explorer dans l'interpréteur, dynamiquement, interactivement
(12:25:42) davin.baragiotta: on ne veut pas coder une ligne dans views.py... faire refresh... réessayer... faire refresh
(12:25:44) davin.baragiotta: c'est nul
(12:25:45) davin.baragiotta: donc
(12:26:01) davin.baragiotta: on explore dans interpréteur... et ce qui nous plait, on le mettre dans views.py
(12:26:08) davin.baragiotta: attention
(12:26:28) davin.baragiotta: pour lancer interpréteur... oui on peut faire directement : ipython ou python
(12:26:29) davin.baragiotta: mais
(12:26:47) davin.baragiotta: tout le contexte django ne sera pas chargé... notamment les settings...
(12:27:03) davin.baragiotta: bref on veut Django avc nous... donc on va lancer l'interpréteur VIA django :
(12:27:09) davin.baragiotta: 
python manage.py shell
(12:27:45) davin.baragiotta: vous avez la puissance de votre interpréteur favori qui vient d'être lancé (moi = ipython)
(12:27:57) davin.baragiotta: on va importer nos modèles pour jouer avec
(12:28:04) davin.baragiotta: pour appeler les données dans la DB
(12:28:25) davin.baragiotta: 
from annuaire.models import Etablissement, Personne
(12:28:44) davin.baragiotta: ok, regardez la doc de l'atelier svp
(12:28:53) davin.baragiotta: etablissements = Etablissement.objects.all()
(12:29:10) davin.baragiotta: sur nos classes qu'on a importé... vis "objects"
(12:29:17) davin.baragiotta: c'est lui l'ORM...
(12:29:31) davin.baragiotta: il nous donne accès aux "objects" de la classe Etablissement...
(12:29:43) davin.baragiotta: sur objects, on a des commandes... des méthodes
(12:29:54) davin.baragiotta: .all() : sélectionne tous les objets
(12:29:56) davin.baragiotta: preuve
(12:30:08) davin.baragiotta: on a stocké le résultat de cet appel dasn variable etablissements
(12:30:14) davin.baragiotta: type(etablissements)
(12:30:39) davin.baragiotta: ah, cette var est un QuerySet... c'est l'ensemble des résultats (rows) de requête à la DB ;)
(12:30:45) davin.baragiotta: on peut itérer dessus
(12:30:49) davin.baragiotta: faire un for
(12:31:02) davin.baragiotta: 
for e in etablissements:
    print e
(12:31:21) davin.baragiotta: on voit les établissemetns
(12:31:22) davin.baragiotta: :D
(12:31:41) davin.baragiotta: si on en veut juste le premier, pour l'explorer :
(12:31:46) davin.baragiotta: e = etablissements[0]
(12:31:49) davin.baragiotta: e.nom
(12:31:51) davin.baragiotta: e.sigle
(12:31:53) davin.baragiotta: :D
(12:32:07) davin.baragiotta: ça marche?
(12:32:10) davin.baragiotta: des questions?
(12:32:34) shafeek.sumser: non on suit attentivement
(12:32:35) davin.baragiotta: ok
(12:32:39) davin.baragiotta: super :D
(12:32:51) davin.baragiotta: on va essayer autre chose
(12:33:02) davin.baragiotta: on va appeler directement une Personne dans la DB
(12:33:13) davin.baragiotta: p = Personne.objects.get(id=1)
(12:33:28) davin.baragiotta: on disait que Django ajoutait automatiquement le champs id à nos objets...
(12:33:35) davin.baragiotta: là on l,utilise pour avoir la personne 1
(12:33:44) davin.baragiotta: (devrait être moi ;) )
(12:33:48) davin.baragiotta: le .get()
(12:33:58) davin.baragiotta: se transforme en WHERE id=1
(12:33:59) davin.baragiotta: :D
(12:34:05) davin.baragiotta: nous on code pas de SQL :D
(12:34:11) davin.baragiotta: on laisse ça à eric.mcsween ;)
(12:34:22) davin.baragiotta: p.id
(12:34:24) davin.baragiotta: p.nom
(12:34:27) davin.baragiotta: p.prenom
(12:34:31) davin.baragiotta: p. + tab?
(12:34:42) davin.baragiotta: quels sont les autres champs de p?
(12:34:45) davin.baragiotta: type(p)
(12:34:53) davin.baragiotta: ça c'est de l'introspection mes amis...
(12:35:04) davin.baragiotta: bien sûr, y,a la doc Django pour nous aider...
(12:35:51) davin.baragiotta: 
In [2]: p = Personne.objects.get(id=1)
In [3]: p.id
Out[3]: 1
In [4]: p
Out[4]: <Personne: LEMAY Paul>
In [5]: p.nom
Out[5]: u'Lemay'
In [6]: p.prenom
Out[6]: u'Paul'
In [7]: p.
p.DoesNotExist                    p.__reduce_ex__                   p._meta
p.MultipleObjectsReturned         p.__repr__                        p._set_pk_val
p.__class__                       p.__setattr__                     p.date_naissance
p.__delattr__                     p.__sizeof__                      p.delete
p.__dict__                        p.__str__                         p.id
p.__doc__                         p.__subclasshook__                p.nom
p.__eq__                          p.__unicode__                     p.objects
p.__format__                      p.__weakref__                     p.pk
p.__getattribute__                p._base_manager                   p.prenom
p.__hash__                        p._collect_sub_objects            p.prepare_database_save
p.__init__                        p._default_manager                p.save
p.__metaclass__                   p._deferred                       p.save_base
p.__module__                      p._get_FIELD_display              p.serializable_value
p.__ne__                          p._get_next_or_previous_by_FIELD  p.universite
p.__new__                         p._get_next_or_previous_in_order  p.universite_id
p.__reduce__                      p._get_pk_val   
(12:36:00) shafeek.sumser: id=2 = davin :D
(12:36:06) davin.baragiotta: zut, c'est pas moi, c'est Paul Lemay ;)
(12:36:10) davin.baragiotta: mon dummy guy ;)
(12:36:23) davin.baragiotta: ok on voit aussi qu'on a un champ universite
(12:36:32) davin.baragiotta: c'est le ForeignKey!
(12:36:43) davin.baragiotta: allez voir annuaire/models.py, pour rappel
(12:37:01) davin.baragiotta: p.universite
(12:37:27) davin.baragiotta: 
In [7]: p.universite
Out[7]: <Etablissement: Université Laval>
In [8]: p.universite.sigle
Out[8]: u'UL'
(12:37:43) davin.baragiotta: ouah... en Python on peut chainer les appels aux objets ;)
(12:37:58) davin.baragiotta: sigle de l'université de la personne
(12:38:09) davin.baragiotta: finalement...
(12:38:14) davin.baragiotta: y,a aussi filter()
(12:38:25) davin.baragiotta: pour faire un WHERE complexe :
(12:38:55) davin.baragiotta: personnes = Personne.objects.filter(nom="Baragiotta")
(12:39:19) davin.baragiotta: 
In [9]: personnes = Personne.objects.filter(nom="Baragiotta")
In [10]: personnes
Out[10]: [<Personne: BARAGIOTTA Davin>]
In [11]: personnes.count()
Out[11]: 1
(12:39:28) davin.baragiotta: suis-je le seul a avoir ce nom?
(12:39:32) davin.baragiotta: oui, dans cette DB ;)
(12:39:54) davin.baragiotta: mais... ceux qui commencent avec la lettre 'B'?
(12:40:19) davin.baragiotta: 
In [12]: personnes = Personne.objects.filter(nom__startswith="B")
In [13]: personnes
Out[13]: [<Personne: BARAGIOTTA Davin>]
(12:40:30) davin.baragiotta: remarquez __startswith
(12:40:41) davin.baragiotta: c'est des "lookup"
(12:40:46) davin.baragiotta: que django offre
(12:40:47) davin.baragiotta: :D
(12:41:05) davin.baragiotta: on peut mettre plusieurs critères
(12:41:52) davin.baragiotta: 
In [14]: personnes = Personne.objects.filter(nom="Baragiotta", prenom="Davin")
In [15]: personnes
Out[15]: [<Personne: BARAGIOTTA Davin>]
In [16]: personnes = Personne.objects.filter(nom="Baragiotta", prenom="Derek")
In [17]: personnes
Out[17]: []
(12:42:03) davin.baragiotta: mon frère n'est pas dans la DB ;)
(12:42:14) davin.baragiotta: bon dernier truc dans notre exploration de l'ORM :
(12:42:20) davin.baragiotta: 
personnes = Personne.objects.filter(etablissement__nom__contains='Montréal')
(12:42:34) davin.baragiotta: erreur
(12:42:37) davin.baragiotta: je modifie la doc ;)
(12:43:01) davin.baragiotta: en fait c,estlogique : je n'ai pas de champ Personne.etablissement
(12:43:10) davin.baragiotta: j'ai juste Personne.universite
(12:43:16) davin.baragiotta: (voir annuaire/models.py
(12:43:51) davin.baragiotta: personnes = Personne.objects.filter(universite__nom__contains='Montréal')
(12:44:13) davin.baragiotta: 
In [19]: personnes = Personne.objects.filter(universite__nom__contains='Montréal')
In [20]: personnes.count()
Out[20]: 2
In [21]: personnes
Out[21]: [<Personne: BARAGIOTTA Davin>, <Personne: TREMBLAY Hughes>]
(12:44:36) davin.baragiotta: 2 personnes sont dans une université ayant, dans son nom, le string "Montréal"
(12:44:38) davin.baragiotta: :D
(12:44:52) davin.baragiotta: on commence à être puissant sur les requêtes de la DB
(12:44:59) davin.baragiotta: mais revenons aux choses simples :
(12:45:09) davin.baragiotta: affichons sur l'accueil, la liste des établissements
(12:45:18) davin.baragiotta: questions sur ORM avant de continuer?
(12:45:33) niry.andriambelo: non
(12:45:42) davin.baragiotta: okay
(12:45:53) davin.baragiotta: codons dans views.py :
(12:46:14) davin.baragiotta: appelons les établissements, exactemwent comme on l'a fait dans interpréteur
(12:46:22) davin.baragiotta: et passons la variable au template
(12:47:10) davin.baragiotta: 
from django.shortcuts import render_to_response
from django.template import Context, RequestContext
from carto_1_1.annuaire.models import Etablissement, Personne
def home(request):
    variable = "Davin"
    etablisements = Etablissement.objects.all()
    c = {
        'var':variable,
    }
    return render_to_response("home.html", Context(c), context_instance = RequestContext(request))
(12:47:22) davin.baragiotta: refresh
(12:47:49) davin.baragiotta: ok rien de neuf : donc pas de problème dans le code de views ;) (n'oubliez pas l'import des modèles)
(12:48:15) davin.baragiotta: reste plus qu'à utiliser cette nouvelle variable dans home.html :
(12:48:39) davin.baragiotta: aie...
(12:48:53) davin.baragiotta: j,ai justement oublié de passer la variable en contexte au template :(
(12:49:02) davin.baragiotta: 
    c = {
        'var':variable,
    }
(12:49:04) davin.baragiotta: :(
(12:49:23) davin.baragiotta: 
    c = {
        'var':variable,
        'etablissements':etablissements,
    }
(12:49:25) davin.baragiotta: :)
(12:50:04) davin.baragiotta: aie... avec erreur dans nom variable :
(12:50:09) davin.baragiotta: 
    etablisements = Etablissement.objects.all()
(12:50:11) davin.baragiotta: :(
(12:50:16) davin.baragiotta:     etablissements = Etablissement.objects.all()
(12:50:18) davin.baragiotta: :)
(12:50:26) davin.baragiotta: bon code final propre :
(12:50:32) davin.baragiotta: 
from django.shortcuts import render_to_response
from django.template import Context, RequestContext
from carto_1_1.annuaire.models import Etablissement, Personne
def home(request):
    variable = "Davin"
    etablissements = Etablissement.objects.all()
    c = {
        'var':variable,
        'etablissements':etablissements,
    }
    return render_to_response("home.html", Context(c), context_instance = RequestContext(request))
(12:50:47) davin.baragiotta: si on ajoute dans template home.html :
(12:50:52) davin.baragiotta: {{ etablissements }}
(12:50:55) davin.baragiotta: ça marche
(12:50:58) davin.baragiotta: mais c,est laid
(12:51:05) davin.baragiotta: (comme dans interpréteur)
(12:51:11) davin.baragiotta: il affiche le queryset....
(12:51:24) davin.baragiotta: faut boulcer dessus.... faire un for
(12:51:30) davin.baragiotta: et afficher chaque établissement
(12:51:38) davin.baragiotta: aidons nous de la doc Django :
(12:51:44) davin.baragiotta: https://docs.djangoproject.com/en/1.1//
(12:52:03) davin.baragiotta: template layer : built-in tags and filters
(12:52:04) davin.baragiotta: https://docs.djangoproject.com/en/1.1//ref/templates/builtins/#ref-templates-builtins
(12:52:23) davin.baragiotta: filters, c,est comme les filtres de SPIP : |filtre()
(12:52:39) davin.baragiotta: mais tags : c'est très puissant... c'est le langage de template de Django
(12:52:50) davin.baragiotta: à droite... la liste de tous les tags...
(12:52:52) davin.baragiotta: tiens...
(12:52:54) davin.baragiotta: un for!
(12:53:02) davin.baragiotta: https://docs.djangoproject.com/en/1.1//ref/templates/builtins/#for
(12:53:10) davin.baragiotta: la syntaxe est :
(12:53:16) davin.baragiotta: {% for ... %}
(12:53:19) davin.baragiotta: pas {{ }}
(12:53:21) davin.baragiotta: et
(12:53:33) davin.baragiotta: faut fermer les tags avec un tag équivalent :
(12:53:38) davin.baragiotta: {% endtag %}
(12:53:40) davin.baragiotta: ici :
(12:53:45) davin.baragiotta: {% endfor %}
(12:53:58) davin.baragiotta: c'est laid... mais c'est plus du Python...
(12:54:01) davin.baragiotta: ;)
(12:54:04) davin.baragiotta: ok on code :
(12:54:40) davin.baragiotta: 
{% for e in etablissements %}
    {{ e }}
{% endfor %}
(12:54:44) davin.baragiotta: refresh
(12:54:55) davin.baragiotta: c'est mieux.... mais ce serait encore mieux avec du HTML
(12:54:58) davin.baragiotta: une liste...
(12:55:01) davin.baragiotta: ou une table
(12:55:33) davin.baragiotta: <ul>
{% for e in etablissements %}
    <li>{{ e }}</li>
{% endfor %}
</ul>
(12:55:36) davin.baragiotta: 
<ul>
{% for e in etablissements %}
    <li>{{ e }}</li>
{% endfor %}
</ul>
(12:55:44) davin.baragiotta: ouaaaaaaaaaaah!!!!
(12:56:14) davin.baragiotta: je sais que dans votre coeur... vous voyez cette liste... et vous brûlez de coder une page de détail pour chaque établissement ;)
(12:56:37) davin.baragiotta: des questions sur l'utilisation réelle de l'ORM et le tag {% for %} ?
(12:56:54) niry.andriambelo: non :)
(12:56:58) davin.baragiotta: bon...
(12:57:05) davin.baragiotta: alors regardons le plan de match
(12:57:24) davin.baragiotta: en passant, reste 3 minutes à l'horaire prévu, mais on a 30 minutes de retard...
(12:57:35) davin.baragiotta: j'ai l'impression qu'on a perdu des joueurs aussi ;)
(12:57:54) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(12:58:02) niry.andriambelo: un autre petit point sur tech ?
(12:58:30) davin.baragiotta: oui... qui suit? mettre un . sur tech
(12:58:59) davin.baragiotta: ok, il y a foule
(12:59:12) davin.baragiotta: nous sommes rendu à l'héritage des templates
(12:59:22) davin.baragiotta: vous savez que notre page home.html
(12:59:29) davin.baragiotta: n'est pas du HTML bien formé
(12:59:31) davin.baragiotta: c'est mal
(12:59:39) davin.baragiotta: on devrait avoir un truc du genre :
(13:00:33) davin.baragiotta: 
<html>
<head>
  <title>Annuaire de l'AUF</title>
</head>
<body>
<h1>Bonjour AUF</h1>
{{ var }}
{{ etablissements }}
<ul>
{% for e in etablissements %}
    <li>{{ e }}</li>
{% endfor %}
</ul>
</body>
</html>
(13:00:39) davin.baragiotta: html, head, title, body
(13:01:11) davin.baragiotta: mais on veut *vraiment* pas coder tout ça dans cahque page de notre site
(13:01:17) davin.baragiotta: c'est contre le principe DRY
(13:01:27) davin.baragiotta: don't repeat yourself : ne te répètes pas
(13:01:37) davin.baragiotta: alors on va centraliser le code
(13:01:46) davin.baragiotta: et faire hériter nos pages avec ce code
(13:01:58) davin.baragiotta: créons un template de base... nommé : base.html
(13:02:08) davin.baragiotta: dans templates, à côté de home.html
(13:02:38) davin.baragiotta: 
<html>
<head>
  <title>Annuaire de l'AUF</title>
</head>
<body>
</body>
</html>
(13:02:57) davin.baragiotta: on veut rendre le body variable... (c'est ce qui varie de page en page)
(13:03:07) davin.baragiotta: on va donc décalrer un block
(13:03:11) davin.baragiotta: c'est un autre tag
(13:03:12) davin.baragiotta: donc :
(13:03:24) davin.baragiotta: 
{% block main %}
(13:03:29) davin.baragiotta: les tags, ça se ferme
(13:03:33) davin.baragiotta: donc on ajoute :
(13:03:38) davin.baragiotta: {% endblock %}
(13:03:54) davin.baragiotta: 
<html>
<head>
  <title>Annuaire de l'AUF</title>
</head>
<body>
{% block main %}
{% endblock %}
</body>
</html>
(13:04:13) davin.baragiotta: ok... maintenant, on va faire hériter home.html de ce template de base :
(13:04:16) davin.baragiotta: home.html :
(13:04:19) davin.baragiotta: en haut :
(13:04:29) davin.baragiotta: {% extends "base.html" %}
(13:04:52) davin.baragiotta: et finalement
(13:05:09) davin.baragiotta: on va dire que le contenu qu'on avait dans home.html... ben il va dans le block main
(13:05:34) davin.baragiotta: 
{% extends "home.html" %}
{% block main %}
<h1>Bonjour AUF</h1>
{{ var }}
{{ etablissements }}
<ul>
{% for e in etablissements %}
    <li>{{ e }}</li>
{% endfor %}
</ul>
{% endblock %}
(13:05:49) davin.baragiotta: faites un refresh de /
(13:06:07) davin.baragiotta: aaaah
(13:06:09) davin.baragiotta: erreur
(13:06:14) davin.baragiotta: récursion ;)
(13:06:19) davin.baragiotta: {% extends "home.html" %}
(13:06:23) davin.baragiotta: base.html
(13:06:24) davin.baragiotta: ;)
(13:06:34) davin.baragiotta: 
{% extends "base.html" %}
{% block main %}
<h1>Bonjour AUF</h1>
{{ var }}
{{ etablissements }}
<ul>
{% for e in etablissements %}
    <li>{{ e }}</li>
{% endfor %}
</ul>
{% endblock %}
(13:06:43) davin.baragiotta: ok
(13:06:52) davin.baragiotta: regardez les sources de la page : ctrl+u
(13:07:11) davin.baragiotta: excellent... les balises sont bien là ;)
(13:07:23) davin.baragiotta: c'était l'héritage des templates ;)
(13:07:24) davin.baragiotta: :D
(13:07:39) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(13:07:49) davin.baragiotta: créons maintenant une page de détail...
(13:07:55) davin.baragiotta: là on n'est plus dans la config...
(13:08:01) davin.baragiotta: on est dans du vrai développement
(13:08:22) davin.baragiotta: quand votre directeur vous dit "ouais ce serait bien une page qui fait ça" ;)
(13:08:28) davin.baragiotta: donc on ajoute les pages... ;)
(13:08:35) davin.baragiotta: quel processus suivre?
(13:08:47) davin.baragiotta: on codons en suivant le flux d'exécution :
(13:09:01) davin.baragiotta: urls.py > views.py > templates
(13:09:14) davin.baragiotta: codons une page de détail pour un établissement
(13:09:27) davin.baragiotta: (on veut tout voir ce qu'on sait sur cet établissemetn)
(13:09:32) davin.baragiotta: commençons par urls.py
(13:09:54) davin.baragiotta: ajoutons une règle en copiant celle du home
(13:10:05) davin.baragiotta: ah... mieux... minute
(13:10:34) davin.baragiotta: enfin non copions
(13:10:53) davin.baragiotta: il fautr miantenant choisir une URL pour le détail d'un établissent
(13:11:13) davin.baragiotta: on veut de belles URLs, c'Est important en 2012... et on fait pas du PHP ;)
(13:11:14) davin.baragiotta: (oups)
(13:11:35) davin.baragiotta: http://127.0.0.1:8000/etablissements/123
(13:11:39) davin.baragiotta: par exemple?
(13:11:52) davin.baragiotta: on pourrait discuter si on met au pluriel ou pas...
(13:12:05) davin.baragiotta: mais par convention, adns URL, on met au pluriel
(13:12:08) davin.baragiotta: donc
(13:12:28) davin.baragiotta: 
    url(r'^etablissements/123$', 'carto_1_1.views.home', name='home'),
(13:12:35) davin.baragiotta: on peut changer son nom, déjà...
(13:12:42) davin.baragiotta: c'est la page détail d'un établissement :
(13:12:50) davin.baragiotta: etablissement_detail
(13:13:02) davin.baragiotta: 
    url(r'^etablissements/123$', 'carto_1_1.views.home', name='etablissement_detail'),
(13:13:06) davin.baragiotta: ok...
(13:13:13) davin.baragiotta: mais là... 123 c'est une constante...
(13:13:23) davin.baragiotta: ça veut dire que si tu mets pas 123 ça amrche
(13:13:24) davin.baragiotta: pas
(13:13:42) davin.baragiotta: et surtout... on veut que ça varie pour chaque etablissement...
(13:14:04) davin.baragiotta: là, faut connaitre les regex.... et moi je copie-colle toujours car de tête c'est pas évident :
(13:14:38) davin.baragiotta: minute, je donne la solution :
(13:15:25) davin.baragiotta: 
url(r'^etablissement/(?P<id>\d+)$', 'carto_1_1.views.home', name="etablissement"),
(13:15:27) davin.baragiotta: bon
(13:15:35) davin.baragiotta: le pattern se lit ainsi :
(13:16:29) davin.baragiotta: si y'a une groupe () qui a un ou plus + digits \d.... alors capte ce groupe dans une param ?P nommé id <id>
(13:16:31) davin.baragiotta: ouais, bon...
(13:16:33) davin.baragiotta: ;)
(13:16:38) davin.baragiotta: finalement
(13:16:50) davin.baragiotta: reste que la fonction appelée à changer....
(13:16:57) davin.baragiotta: reste 15 minutes...
(13:17:14) davin.baragiotta: je vais vous montrer tout ça, si vous permettez, (avec autres choses)... dans le code final
(13:17:17) davin.baragiotta: d'accord?
(13:17:35) davin.baragiotta: nous resterait à coder la views.py et le template html...
(13:17:36) niry.andriambelo: d'accord (j'imagine)
(13:17:38) niry.andriambelo: :)
(13:17:41) davin.baragiotta: on fait un saut dans le temps!
(13:17:47) davin.baragiotta: ouais, on est d'accord ;)
(13:18:12) davin.baragiotta: voici les sources finales à télécharger et extraire... attention, ça s'appelle aussi carto_1_1
(13:18:21) davin.baragiotta: désolé, j'organiserai mieux :
(13:18:37) davin.baragiotta: http://git.auf.org/?p=davin.git;a=snapshot;h=0f355ca952ddf8f9c7636226904a5fcb04ee53dc;sf=tgz
(13:19:21) davin.baragiotta: c'est davin-0f355ca/ateliers/django/carto_1_1
(13:19:28) davin.baragiotta: qui nous intéresse
(13:19:44) davin.baragiotta: je le mets direct dans mon home
(13:20:19) davin.baragiotta: 
davin.baragiotta@u-db:~/carto_1_1$ ls
annuaire  carto.db  __init__.py  manage.py  media  settings.py  templates  urls.py  views.py
(13:20:22) davin.baragiotta: ok mes amis...
(13:20:30) davin.baragiotta: attention au clou de la journée
(13:20:31) shafeek.sumser: oui pareil comme indiqué
(13:20:40) davin.baragiotta: le feu d'artifice Django :
(13:20:47) davin.baragiotta: 
python manage.py runserver
(13:20:53) davin.baragiotta: (fermer l'autre avant...)
(13:21:32) davin.baragiotta: http://127.0.0.1:8000/
(13:21:36) davin.baragiotta: tadaaaaaaaaaaaaaaaaaaaaam!!!!
(13:22:00) davin.baragiotta: on l'a tous?
(13:22:44) davin.baragiotta: ok ce code = le code final des 2 ateliers backend et frontend
(13:22:55) davin.baragiotta: vous pouvez voir annuaire/admin.py
(13:23:03) davin.baragiotta: et tester dans l'admin : les filtres à droite...
(13:23:09) davin.baragiotta: la recherche dans Personne
(13:23:16) davin.baragiotta: les colonnes dans les listings
(13:23:20) davin.baragiotta: rien de sorcier ;)
(13:23:24) davin.baragiotta: mais très utile...
(13:23:47) davin.baragiotta: pour cet atelier frontend : couvrons rapidement les nouveautés de ce code
(13:23:54) davin.baragiotta: 1. les URLs avec param
(13:24:00) davin.baragiotta: ce qu'on avait commencé à codé...
(13:24:06) davin.baragiotta: je vous montre dans :
urls.py
(13:24:19) davin.baragiotta: 
    # annuaire
    (r'^', include('carto_1_1.annuaire.urls')),
(13:25:01) davin.baragiotta: en fait... toutes les URL qui ne matchent pas dans urls.py.... on les envoient tester dans annuaire.urls
(13:25:06) davin.baragiotta: annuaire.urls.py :
(13:25:21) davin.baragiotta: 
# -*- encoding: utf-8 -*-
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('carto_1_1.annuaire.views',
    # établissements
    url(r'^etablissements$', 'etablissement_list', name="etablissements"),
    url(r'^etablissement/(?P<id>\d+)$', 'etablissement_detail', name="etablissement"),
    # personnes
    url(r'^personnes$', 'personne_list', name="personnes"),
    url(r'^personne/(?P<id>\d+)$', 'personne_detail', name="personne"),
)
(13:25:26) davin.baragiotta: pareil que urls.py
(13:25:34) davin.baragiotta: 
    url(r'^etablissement/(?P<id>\d+)$', 'etablissement_detail', name="etablissement"),
(13:25:40) davin.baragiotta: c'est ce qu'on codait...
(13:25:49) davin.baragiotta:     url(r'^etablissements$', 'etablissement_list', name="etablissements"),
(13:25:58) davin.baragiotta: tiens... la liste complète des établissements
(13:26:03) davin.baragiotta: essayons cette URL :
(13:26:13) davin.baragiotta: ilen établissemetns dans interface :
(13:26:14) davin.baragiotta: http://127.0.0.1:8000/etablissements
(13:26:33) davin.baragiotta: super avec un lien sur chaque
(13:26:40) davin.baragiotta: on clique sur un établissement
(13:26:45) davin.baragiotta: http://127.0.0.1:8000/etablissement/1
(13:27:05) davin.baragiotta: on suit le traitement de l'info :
urls.py > annuaire/urls.py >
(13:27:31) davin.baragiotta: puis annuaire/views.py (préfixe de tous mes pattenrs :
'carto_1_1.annuaire.views'
)
(13:27:46) davin.baragiotta: et on cherche fonction 'etablissement_detail'
(13:27:54) davin.baragiotta: lisons views.py
(13:28:01) davin.baragiotta: dans annuaire
(13:28:09) davin.baragiotta: 
def etablissement_detail(request, id):
    etablissement = Etablissement.objects.get(id=id)
    c = {
        'etablissement': etablissement,
    }
    return render_to_response("annuaire/etablissement_detail.html", Context(c), context_instance = RequestContext(request))
(13:28:22) davin.baragiotta: on ajoute le paramètre id capté par pattern url
(13:28:23) davin.baragiotta: :)
(13:28:29) davin.baragiotta: on fait un .get()
(13:28:35) davin.baragiotta: comme vu en explorant l'ORM
(13:28:43) davin.baragiotta: on passe l'établissement au template
(13:28:50) davin.baragiotta: annuaire/etablissement_detail.html
(13:29:12) davin.baragiotta: on a un répertoire templates dans l'app annuaire :
(13:29:15) davin.baragiotta: ouvrons
(13:29:47) davin.baragiotta: carto_1_1/annuaire/templates/annuaire/etablissement_detail.html
(13:29:57) davin.baragiotta: violà...
(13:30:03) davin.baragiotta: on sait tout faire ça :
(13:30:06) davin.baragiotta: {{ }}
(13:30:10) davin.baragiotta: {% for %}
(13:30:16) davin.baragiotta: reste juste tag {% url
(13:30:18) davin.baragiotta: un mot :
(13:30:35) davin.baragiotta: sont but = générer l'URL complète à partir des noms de noms patterns d'URL :
(13:30:38) davin.baragiotta: ;D
(13:30:41) davin.baragiotta: :D
(13:30:49) davin.baragiotta:     <li><a href="{% url personne p.id %}">{{ p }}</a></li>
(13:30:50) davin.baragiotta: se lit :
(13:31:22) davin.baragiotta: génère moi l'URL complète de l'URL gérée par le pattern nommé "personne"... et je te passe le id du p en cours
(13:31:24) davin.baragiotta: p.id
(13:31:28) davin.baragiotta: ça donne ceci
(13:31:35) davin.baragiotta: http://127.0.0.1:8000/personne/2
(13:31:46) davin.baragiotta: car on a ce pattern nommé "personne"
(13:31:57) davin.baragiotta: 
    url(r'^personne/(?P<id>\d+)$', 'personne_detail', name="personne"),
(13:32:06) davin.baragiotta: dans annuaire/urls.py
(13:32:15) davin.baragiotta: ça s'appelle faire du reverse url
(13:32:18) davin.baragiotta: voilà
(13:32:29) davin.baragiotta: quaoi d'autres.... explorez rapido les interfaces : 
(13:32:35) davin.baragiotta: on a de la mécanique de connexion
(13:32:43) davin.baragiotta: c'est simple :
(13:32:56) davin.baragiotta: urls.py, settings.py + connexion.html et deconnexion.html
(13:33:01) davin.baragiotta: testez, ça marche!
(13:33:07) davin.baragiotta: user : admin, pass : admin
(13:33:13) shafeek.sumser: testé
(13:33:26) davin.baragiotta: avec lien vers admin en haut, of course ;)
(13:33:28) davin.baragiotta: bon voilà
(13:33:40) davin.baragiotta: regardons ce qui manque dans plan de match : (non couvert)
(13:33:53) davin.baragiotta: https://wiki.auf.org/wikiteki/Ateliers/Django/Frontend/Support
(13:34:07) davin.baragiotta: ah oui... la magie du design
(13:34:12) davin.baragiotta: tout est dans :
(13:34:20) davin.baragiotta: répertoire /media/... css et images
(13:34:34) davin.baragiotta: settings.py dit où se trouve les media : MEDIA_URL
(13:34:53) davin.baragiotta: et le template de base... base.html... vraiment étoffé... utilise ces styles : {{ MEDIA_URL }}
(13:35:09) davin.baragiotta: finissons avec les sources de base.html :
(13:35:10) davin.baragiotta: ;)
(13:35:30) davin.baragiotta: ça... on veut pas coder ça dans toutes nos pages!
(13:35:45) davin.baragiotta: un chance qu'on a un framework de développement qui offre héritage de template!
(13:35:51) davin.baragiotta: c'était l,atelier sur frontend
(13:36:02) davin.baragiotta: vous savez maintenant monter des interfaces web avec Django
(13:36:14) davin.baragiotta: pour afficher au public les données gérées dans l'admin
(13:36:20) davin.baragiotta: des questions?
(13:36:46) niry.andriambelo: shafeek.sumser: Q: par contre le base.html se situe dans le dossier racine du projet! 
(13:37:02) niry.andriambelo: mais je viens de verifier c'est bien dans templates pour moi
(13:37:27) davin.baragiotta: 
(13:36:59) giotta: ouais... l'app reste couplée... tout ne peut pas être 100% coupé
(13:37:12) giotta: mais c'est pas la job de l'app de décider du design global ;)
(13:38:11) davin.baragiotta: oui, shafeek.sumser a raison :
carto_1_1/templates/base.html
(13:38:27) davin.baragiotta: utilisé par les templates de 
carto_1_1/annuaire/templates/...
(13:38:28) davin.baragiotta: ;)
(13:39:02) davin.baragiotta: mais en gros : c,est un détail de design génie logiciel... mais tout réorganiser c'est très facile, si on n,est pas content ;)
(13:39:23) davin.baragiotta: ----------------------- FIN ATELIER DJANGO : frontend ---------------------------

Ateliers/2012-08-31 (dernière édition le 2012-09-11 23:08:33 par DavinBaragiotta)