├── resultats └── .gitkeep ├── cours-flask ├── __init__.py ├── exemple12 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ └── metadata.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ └── place.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ └── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ ├── app.py │ │ └── routes.py │ ├── run.py │ └── path.py ├── exemple13 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ └── metadata.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ ├── recherche.html │ │ │ │ └── place.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ └── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ ├── app.py │ │ └── routes.py │ ├── run.py │ └── path.py ├── exemple14 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ ├── metadata.html │ │ │ │ └── recherche.html │ │ │ ├── pages │ │ │ │ ├── recherche.html │ │ │ │ ├── accueil.html │ │ │ │ └── place.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── images │ │ │ │ └── gallica_btv1b55007071f.jpeg │ │ ├── app.py │ │ └── routes.py │ ├── run.py │ └── path.py ├── exemple15 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ ├── metadata.html │ │ │ │ └── recherche.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ ├── place.html │ │ │ │ └── recherche.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── images │ │ │ │ └── gallica_btv1b55007071f.jpeg │ │ ├── app.py │ │ └── routes.py │ ├── run.py │ └── path.py ├── exemple16 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── routes │ │ │ ├── api.py │ │ │ └── generic.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── donnees.py │ │ │ └── utilisateurs.py │ │ ├── templates │ │ │ ├── pages │ │ │ │ ├── browse.html │ │ │ │ ├── accueil.html │ │ │ │ ├── place.html │ │ │ │ ├── connexion.html │ │ │ │ ├── recherche.html │ │ │ │ └── inscription.html │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ ├── metadata.html │ │ │ │ └── recherche.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── images │ │ │ │ └── gallica_btv1b55007071f.jpeg │ │ ├── constantes.py │ │ └── app.py │ ├── run.py │ └── path.py ├── exemple17 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── donnees.py │ │ │ └── utilisateurs.py │ │ ├── routes │ │ │ ├── __init__.py │ │ │ └── api.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ ├── metadata.html │ │ │ │ └── recherche.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ ├── place.html │ │ │ │ ├── connexion.html │ │ │ │ ├── browse.html │ │ │ │ ├── recherche.html │ │ │ │ └── inscription.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── images │ │ │ │ └── gallica_btv1b55007071f.jpeg │ │ ├── constantes.py │ │ ├── app.py │ │ └── routes.py │ ├── run.py │ └── path.py ├── exemple18 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── donnees.py │ │ │ └── utilisateurs.py │ │ ├── routes │ │ │ ├── __init__.py │ │ │ └── api.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ ├── metadata.html │ │ │ │ └── recherche.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ ├── place.html │ │ │ │ ├── connexion.html │ │ │ │ ├── browse.html │ │ │ │ ├── recherche.html │ │ │ │ └── inscription.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── images │ │ │ │ └── gallica_btv1b55007071f.jpeg │ │ ├── constantes.py │ │ ├── app.py │ │ └── routes.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_user.py │ │ └── test_api.py │ ├── run.py │ └── path.py ├── exemple10 │ ├── templates │ │ ├── partials │ │ │ ├── css.html │ │ │ └── metadata.html │ │ ├── pages │ │ │ ├── accueil.html │ │ │ └── place.html │ │ └── conteneur.html │ ├── static │ │ └── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ └── app.py ├── exemple11 │ ├── templates │ │ ├── partials │ │ │ ├── css.html │ │ │ └── metadata.html │ │ ├── pages │ │ │ ├── accueil.html │ │ │ └── place.html │ │ └── conteneur.html │ ├── static │ │ └── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ └── app.py ├── exemple4 │ ├── templates │ │ └── accueil.html │ └── app.py ├── exemple1 │ └── app.py ├── exemple9 │ ├── templates │ │ ├── partials │ │ │ └── metadata.html │ │ ├── conteneur.html │ │ └── pages │ │ │ ├── accueil.html │ │ │ └── place.html │ └── app.py ├── exemple8 │ ├── templates │ │ ├── conteneur.html │ │ └── pages │ │ │ ├── accueil.html │ │ │ └── place.html │ └── app.py ├── exemple5 │ ├── templates │ │ └── accueil.html │ └── app.py ├── exemple6 │ ├── templates │ │ ├── accueil.html │ │ └── place.html │ └── app.py ├── exemple7 │ ├── templates │ │ ├── accueil.html │ │ └── place.html │ └── app.py ├── exemple2 │ └── app.py ├── exemple3 │ └── app.py └── README.md ├── modules_cours ├── __init__.py ├── gazetteer │ ├── __init__.py │ ├── modeles │ │ ├── __init__.py │ │ ├── donnees.py │ │ └── utilisateurs.py │ ├── constantes.py │ └── app.py ├── chapitre5.py └── chapitre4.py ├── cours-packages ├── exemple-05 │ ├── app │ │ ├── __init__.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ └── truc.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── data.py │ │ │ └── user.py │ │ ├── __main__.py │ │ └── run.py │ └── README.md ├── exemple-02 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles.py │ │ └── application.py │ ├── run.py │ └── run2.py ├── exemple-03 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ └── application.py │ └── run.py ├── exemple-04 │ ├── gazetteer │ │ ├── __init__.py │ │ ├── modeles │ │ │ ├── __init__.py │ │ │ ├── utilisateurs.py │ │ │ └── donnees.py │ │ ├── templates │ │ │ ├── partials │ │ │ │ ├── css.html │ │ │ │ └── metadata.html │ │ │ ├── pages │ │ │ │ ├── accueil.html │ │ │ │ └── place.html │ │ │ └── conteneur.html │ │ ├── static │ │ │ └── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ ├── app.py │ │ └── routes.py │ └── run.py └── exemple-01 │ ├── gazetteer │ └── __init__.py │ └── run.py ├── License.txt ├── images ├── cli.png ├── json.png ├── url.png ├── datamodel.png ├── indexing.png ├── latin.html.png ├── latin.json.png ├── model.place.png ├── model.user.png ├── BackPopulate.png ├── PythonModules.png ├── autocomplete.gif ├── decoupage.site.dia ├── decoupage.site.png ├── json.twitter.png ├── sql.transaction.png ├── twitter.console.png ├── http.request.scheme.png ├── incrustation.site.dia ├── incrustation.site.png ├── http.request.request.png ├── http.request.response.png ├── incrustation.avancee.dia ├── incrustation.avancee.png └── Python-Programming-Language.png ├── requirements.txt ├── data ├── csv │ ├── eggs.csv │ └── pleiades.csv ├── json │ ├── youtube.exemple.json │ └── brecht.json ├── xml │ └── template_tei_exercice.xml ├── lanuitdelamort.michel.txt ├── Ballade.XXVIII.dePisan.txt ├── scripts │ └── download_pleiades.py ├── cid.v1071.1682.txt ├── lettre.louisemichel.txt └── misanthrope.acte3.scene4.txt ├── pdfs └── building beautiful command line interfaces with python.pdf ├── .gitignore ├── supports └── chapitre-6 │ ├── template.wordpress.php │ └── template.omeka.php ├── biliopat.csv ├── exercices ├── Fichiers.ipynb ├── CSV.ipynb └── Fonctions.ipynb ├── README.md └── Chapitre 12 - Jointures SQL et Update - Exercice Jointure.ipynb /resultats/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules_cours/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules_cours/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple18/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules_cours/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/routes/api.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-02/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-03/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/routes/generic.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/routes/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/routes/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-03/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/modeles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/utils/truc.py: -------------------------------------------------------------------------------- 1 | TRUC = "Truc" -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/browse.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-packages/exemple-01/gazetteer/__init__.py: -------------------------------------------------------------------------------- 1 | ma_variable = 0 -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/modeles/data.py: -------------------------------------------------------------------------------- 1 | DATA = "I AM DATA." -------------------------------------------------------------------------------- /cours-packages/exemple-02/gazetteer/modeles.py: -------------------------------------------------------------------------------- 1 | mon_module = "modeles" 2 | -------------------------------------------------------------------------------- /cours-packages/exemple-05/README.md: -------------------------------------------------------------------------------- 1 | Lancez `python app` depuis ce dossier 2 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | See https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr 2 | -------------------------------------------------------------------------------- /cours-packages/exemple-02/gazetteer/application.py: -------------------------------------------------------------------------------- 1 | mon_module = "application" 2 | -------------------------------------------------------------------------------- /cours-packages/exemple-03/gazetteer/application.py: -------------------------------------------------------------------------------- 1 | nom_dapplication = "Gazetteer" -------------------------------------------------------------------------------- /cours-packages/exemple-03/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | mon_utilisateur = "Thibault" -------------------------------------------------------------------------------- /images/cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/cli.png -------------------------------------------------------------------------------- /images/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/json.png -------------------------------------------------------------------------------- /images/url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/url.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | feedparser 2 | requests 3 | lxml 4 | ipython 5 | jupyter 6 | flask 7 | Click -------------------------------------------------------------------------------- /cours-packages/exemple-01/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer import ma_variable 2 | 3 | print(ma_variable) 4 | -------------------------------------------------------------------------------- /data/csv/eggs.csv: -------------------------------------------------------------------------------- 1 | Spam Spam Spam Spam Spam |Baked Beans| 2 | Spam |Lovely Spam| |Wonderful Spam| 3 | -------------------------------------------------------------------------------- /images/datamodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/datamodel.png -------------------------------------------------------------------------------- /images/indexing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/indexing.png -------------------------------------------------------------------------------- /cours-packages/exemple-03/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.modeles.donnees import qui_fait_quoi 2 | 3 | qui_fait_quoi() -------------------------------------------------------------------------------- /images/latin.html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/latin.html.png -------------------------------------------------------------------------------- /images/latin.json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/latin.json.png -------------------------------------------------------------------------------- /images/model.place.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/model.place.png -------------------------------------------------------------------------------- /images/model.user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/model.user.png -------------------------------------------------------------------------------- /images/BackPopulate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/BackPopulate.png -------------------------------------------------------------------------------- /images/PythonModules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/PythonModules.png -------------------------------------------------------------------------------- /images/autocomplete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/autocomplete.gif -------------------------------------------------------------------------------- /images/decoupage.site.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/decoupage.site.dia -------------------------------------------------------------------------------- /images/decoupage.site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/decoupage.site.png -------------------------------------------------------------------------------- /images/json.twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/json.twitter.png -------------------------------------------------------------------------------- /images/sql.transaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/sql.transaction.png -------------------------------------------------------------------------------- /images/twitter.console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/twitter.console.png -------------------------------------------------------------------------------- /cours-flask/exemple12/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-flask/exemple13/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-flask/exemple14/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-flask/exemple15/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-flask/exemple16/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-flask/exemple17/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /images/http.request.scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/http.request.scheme.png -------------------------------------------------------------------------------- /images/incrustation.site.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/incrustation.site.dia -------------------------------------------------------------------------------- /images/incrustation.site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/incrustation.site.png -------------------------------------------------------------------------------- /cours-packages/exemple-04/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import app 2 | 3 | if __name__ == "__main__": 4 | app.run(debug=True) -------------------------------------------------------------------------------- /images/http.request.request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/http.request.request.png -------------------------------------------------------------------------------- /images/http.request.response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/http.request.response.png -------------------------------------------------------------------------------- /images/incrustation.avancee.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/incrustation.avancee.dia -------------------------------------------------------------------------------- /images/incrustation.avancee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/incrustation.avancee.png -------------------------------------------------------------------------------- /cours-flask/exemple10/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple11/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/Python-Programming-Language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/images/Python-Programming-Language.png -------------------------------------------------------------------------------- /cours-packages/exemple-02/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.application import mon_module 2 | from gazetteer.modeles import mon_module 3 | 4 | print(mon_module) -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/templates/partials/css.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cours-flask/exemple10/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple10/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple11/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple11/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple4/templates/accueil.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{nom}} 4 | 5 | Bienvenue ! 6 | -------------------------------------------------------------------------------- /cours-flask/exemple18/run.py: -------------------------------------------------------------------------------- 1 | from gazetteer.app import config_app 2 | 3 | if __name__ == "__main__": 4 | app = config_app("production") 5 | app.run(debug=True) -------------------------------------------------------------------------------- /cours-packages/exemple-02/run2.py: -------------------------------------------------------------------------------- 1 | from gazetteer.application import mon_module as mma 2 | from gazetteer.modeles import mon_module as mmm 3 | 4 | print(mma) 5 | print(mmm) -------------------------------------------------------------------------------- /cours-flask/exemple10/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple10/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple10/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple10/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple10/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple10/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple10/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple10/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple11/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple11/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple11/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple11/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple11/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple11/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple11/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple11/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple12/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple13/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /cours-flask/exemple1/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask("Application") 4 | 5 | @app.route("/") 6 | def index(): 7 | return "Hello world !" 8 | 9 | app.run() 10 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-packages/exemple-04/gazetteer/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /pdfs/building beautiful command line interfaces with python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/pdfs/building beautiful command line interfaces with python.pdf -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple12/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple13/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/static/images/gallica_btv1b55007071f.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple14/gazetteer/static/images/gallica_btv1b55007071f.jpeg -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/static/images/gallica_btv1b55007071f.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple15/gazetteer/static/images/gallica_btv1b55007071f.jpeg -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/static/images/gallica_btv1b55007071f.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple16/gazetteer/static/images/gallica_btv1b55007071f.jpeg -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/static/images/gallica_btv1b55007071f.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple17/gazetteer/static/images/gallica_btv1b55007071f.jpeg -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/static/images/gallica_btv1b55007071f.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-flask/exemple18/gazetteer/static/images/gallica_btv1b55007071f.jpeg -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PonteIneptique/cours-python/HEAD/cours-packages/exemple-04/gazetteer/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /cours-flask/exemple12/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple13/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple14/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple15/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple16/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple17/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple18/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 4 | print(chemin_actuel) 5 | 6 | templates = os.path.join(chemin_actuel, "gazetteer", "templates") 7 | print(templates) 8 | -------------------------------------------------------------------------------- /cours-packages/exemple-03/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .utilisateurs import mon_utilisateur 2 | from ..application import nom_dapplication 3 | 4 | 5 | def qui_fait_quoi(): 6 | print(mon_utilisateur + " utilise " + nom_dapplication) -------------------------------------------------------------------------------- /data/json/youtube.exemple.json: -------------------------------------------------------------------------------- 1 | [{"titre": "Hacking Websites with SQL Injection - Computerphile", "lien": "https://www.youtube.com/watch?v=_jKylhJtPmI"}, {"titre": "Cross Site Request Forgery - Computerphile", "lien": "https://www.youtube.com/watch?v=vRBihr41JTo"}] -------------------------------------------------------------------------------- /modules_cours/gazetteer/constantes.py: -------------------------------------------------------------------------------- 1 | from warnings import warn 2 | 3 | LIEUX_PAR_PAGE = 2 4 | SECRET_KEY = "JE SUIS UN SECRET !" 5 | 6 | if SECRET_KEY == "JE SUIS UN SECRET !": 7 | warn("Le secret par défaut n'a pas été changé, vous devriez le faire", Warning) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/constantes.py: -------------------------------------------------------------------------------- 1 | from warnings import warn 2 | 3 | LIEUX_PAR_PAGE = 2 4 | SECRET_KEY = "JE SUIS UN SECRET !" 5 | 6 | if SECRET_KEY == "JE SUIS UN SECRET !": 7 | warn("Le secret par défaut n'a pas été changé, vous devriez le faire", Warning) 8 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/constantes.py: -------------------------------------------------------------------------------- 1 | from warnings import warn 2 | 3 | LIEUX_PAR_PAGE = 2 4 | SECRET_KEY = "JE SUIS UN SECRET !" 5 | API_ROUTE = "/api" 6 | 7 | if SECRET_KEY == "JE SUIS UN SECRET !": 8 | warn("Le secret par défaut n'a pas été changé, vous devriez le faire", Warning) 9 | -------------------------------------------------------------------------------- /modules_cours/chapitre5.py: -------------------------------------------------------------------------------- 1 | class ObjetExemple: 2 | 3 | def __init__(self): 4 | self.attribut_exemple = 5 5 | 6 | def change_valeur_attribut_exemple(self, valeur): 7 | self.attribut_exemple = valeur 8 | print("Il s'en passe des choses derrière") 9 | 10 | objet_exemple = ObjetExemple() -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/__main__.py: -------------------------------------------------------------------------------- 1 | print("""--------------------------------- 2 | Contenu de __main__ exécuté : 3 | --------------------------------- 4 | 5 | import run 6 | import modeles.user 7 | 8 | --------------------------------- 9 | Résultat : 10 | --------------------------------- 11 | 12 | """) 13 | import run 14 | import modeles.user -------------------------------------------------------------------------------- /cours-flask/exemple10/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple11/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple9/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cours-flask/exemple8/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Gazetteer {%block titre %}{%endblock%} 7 | 8 | 9 |

Bienvenue sur le Gazetteer

10 |
{% block corps%}{%endblock%}
11 | 12 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | 4 | 5 | app = Flask("Application") 6 | # On configure la base de données 7 | app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://gazetteer_user:password@localhost/gazetteer' 8 | # On initie l'extension 9 | db = SQLAlchemy(app) 10 | 11 | from .routes import lieu, accueil -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/templates/partials/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | resultats/*.txt 2 | env/ 3 | .DS_Store 4 | .DS_Store 5 | .ipynb_checkpoints/Chapter 2 - First steps-checkpoint.ipynb 6 | .ipynb_checkpoints/Chapter 5 - Building NLP Applications-checkpoint.ipynb 7 | .ipynb_checkpoints/ 8 | *-checkpoint.ipynb 9 | .pyc 10 | *Copy*.ipynb 11 | *.pyc 12 | .~lock* 13 | __pycache__ 14 | .idea 15 | pyhum 16 | pydf 17 | styles 18 | *.bak 19 | pages.csv 20 | *.sqlite -------------------------------------------------------------------------------- /supports/chapitre-6/template.wordpress.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |

7 |

8 | 9 | 10 |
-------------------------------------------------------------------------------- /cours-packages/exemple-05/app/modeles/user.py: -------------------------------------------------------------------------------- 1 | from modeles.data import DATA 2 | print("app/modeles/user.py", "from modeles.data import DATA", DATA) 3 | from .data import DATA 4 | print("app/modeles/user.py", "from .data import DATA", DATA) 5 | from utils.truc import TRUC 6 | print("app/modeles/user.py", "from utils.truc import TRUC", TRUC) 7 | from run import RUN 8 | print("app/modeles/user.py", "from run import RUN", RUN) -------------------------------------------------------------------------------- /cours-packages/exemple-05/app/run.py: -------------------------------------------------------------------------------- 1 | from modeles.data import DATA 2 | print("app/run.py", "from modeles.data import DATA", DATA) 3 | import modeles 4 | print("app/run.py", "import modeles", modeles.data.DATA) 5 | from modeles.data import DATA 6 | print("app/run.py", "from modeles.data import DATA", DATA) 7 | from utils.truc import TRUC 8 | print("app/run.py", "from utils.truc import TRUC", TRUC) 9 | 10 | RUN = "LET'S RUN" -------------------------------------------------------------------------------- /cours-flask/exemple9/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Gazetteer {%block titre %}{%endblock%} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 |

Bienvenue sur le Gazetteer

11 |
{% block corps%}{%endblock%}
12 | 13 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | class User(db.Model): 5 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 6 | user_nom = db.Column(db.Text, nullable=False) 7 | user_login = db.Column(db.String(45), nullable=False) 8 | user_email = db.Column(db.Text, nullable=False) 9 | user_password = db.Column(db.String(64), nullable=False) -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | class User(db.Model): 5 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 6 | user_nom = db.Column(db.Text, nullable=False) 7 | user_login = db.Column(db.String(45), nullable=False) 8 | user_email = db.Column(db.Text, nullable=False) 9 | user_password = db.Column(db.String(64), nullable=False) -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | class User(db.Model): 5 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 6 | user_nom = db.Column(db.Text, nullable=False) 7 | user_login = db.Column(db.String(45), nullable=False) 8 | user_email = db.Column(db.Text, nullable=False) 9 | user_password = db.Column(db.String(64), nullable=False) -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | class User(db.Model): 5 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 6 | user_nom = db.Column(db.Text, nullable=False) 7 | user_login = db.Column(db.String(45), nullable=False) 8 | user_email = db.Column(db.Text, nullable=False) 9 | user_password = db.Column(db.String(64), nullable=False) -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | class User(db.Model): 5 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 6 | user_nom = db.Column(db.Text, nullable=False) 7 | user_login = db.Column(db.String(45), nullable=False) 8 | user_email = db.Column(db.Text, nullable=False) 9 | user_password = db.Column(db.String(64), nullable=False) -------------------------------------------------------------------------------- /modules_cours/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple5/templates/accueil.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{nom}} 4 | 5 | 6 |

Bienvenue !

7 |

8 | {% if lieux %} 9 | Il y a {{ lieux|length }} enregistrés , voici le premier : {{lieux[0]}} 10 | {% else %} 11 | La base de données est en cours de constitution 12 | {% endif %} 13 |

14 | 15 | -------------------------------------------------------------------------------- /cours-flask/exemple6/templates/accueil.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{nom}} 4 | 5 | 6 |

Bienvenue !

7 |

8 | {% if lieux %} 9 | Il y a {{ lieux|length }} enregistrés , voici le premier : {{lieux[0].nom}} 10 | {% else %} 11 | La base de données est en cours de constitution 12 | {% endif %} 13 |

14 | 15 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from .. app import db 2 | 3 | 4 | # On crée notre modèle 5 | class Place(db.Model): 6 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 7 | place_nom = db.Column(db.Text) 8 | place_description = db.Column(db.Text) 9 | place_longitude = db.Column(db.Float) 10 | place_latitude = db.Column(db.Float) 11 | place_type = db.Column(db.String(45)) 12 | -------------------------------------------------------------------------------- /cours-flask/exemple11/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 | {% if lieux %} 5 |

Il y a {{lieux|length}} lieux enregistrés :

6 | 11 | {% else %} 12 |

La base de données est en cours de constitution

13 | {% endif %} 14 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple10/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 | {% if lieux %} 5 |

Il y a {{lieux|length}} lieux enregistrés :

6 | 11 | {% else %} 12 |

La base de données est en cours de constitution

13 | {% endif %} 14 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 | {% if lieux %} 5 |

Il y a {{lieux|length}} lieux enregistrés :

6 | 11 | {% else %} 12 |

La base de données est en cours de constitution

13 | {% endif %} 14 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 | {% if lieux %} 5 |

Il y a {{lieux|length}} lieux enregistrés :

6 | 11 | {% else %} 12 |

La base de données est en cours de constitution

13 | {% endif %} 14 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 |

{{titre}}

7 | {% if resultats %} 8 |

Il y a {{resultats|length}} lieux qui répondent à votre requête :

9 | 14 | {% endif %} 15 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple8/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 |

5 | {% if lieux %} 6 | Il y a {{lieux|length}} enregistrés : 7 |

12 | {% else %} 13 | La base de données est en cours de constitution 14 | {% endif %} 15 |

16 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple9/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 |

5 | {% if lieux %} 6 | Il y a {{lieux|length}} enregistrés : 7 |

12 | {% else %} 13 | La base de données est en cours de constitution 14 | {% endif %} 15 |

16 | {% endblock %} -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block corps %} 3 |

Bienvenue !

4 | {% if lieux %} 5 |

Il y a {{lieux|length}} lieux enregistrés :

6 | 11 | {% else %} 12 |

La base de données est en cours de constitution

13 | {% endif %} 14 | {% endblock %} -------------------------------------------------------------------------------- /data/xml/template_tei_exercice.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $titre$ 7 | $auteur$ 8 | 9 | 10 |

11 | 12 | 13 |

14 | 15 | 16 | 17 | 18 | 19 | $poeme$ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/partials/recherche.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/partials/recherche.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/partials/recherche.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/partials/recherche.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/partials/recherche.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 | {% include "partials/recherche.html" %} 8 | 9 |

{{titre}}

10 | {% if resultats %} 11 |

Il y a {{resultats|length}} lieux qui répondent à votre requête :

12 | 17 | {% endif %} 18 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | import os 4 | 5 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 6 | templates = os.path.join(chemin_actuel, "templates") 7 | statics = os.path.join(chemin_actuel, "static") 8 | 9 | app = Flask( 10 | "Application", 11 | template_folder=templates, 12 | static_folder=statics 13 | ) 14 | # On configure la base de données 15 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 16 | # On initie l'extension 17 | db = SQLAlchemy(app) 18 | 19 | from .routes import lieu, accueil -------------------------------------------------------------------------------- /cours-flask/exemple4/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | 6 | @app.route("/") 7 | def accueil(): 8 | return render_template("accueil.html", nom="Gazetteer") 9 | 10 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 11 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 12 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 13 | # Le fichier `script.py` a en __name__ la valeur __main__. 14 | if __name__ == "__main__": 15 | app.run() 16 | -------------------------------------------------------------------------------- /modules_cours/chapitre4.py: -------------------------------------------------------------------------------- 1 | from feedparser import parse 2 | 3 | def read_rss(address="http://www.enc-sorbonne.fr/fr/rss"): 4 | """ Read a RSS feed and returns a simpler format 5 | 6 | :param address: URI Address of the RSS Feed 7 | :type address: str 8 | :yields: Tuple of (Title, Summary, Link, Published) 9 | """ 10 | feed = parse(address) 11 | for item in feed["items"]: 12 | line = ( 13 | item["title_detail"]["value"], 14 | item["summary_detail"]["value"], 15 | item["link"], 16 | item["published"] 17 | ) 18 | yield line -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | import os 4 | 5 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 6 | templates = os.path.join(chemin_actuel, "templates") 7 | statics = os.path.join(chemin_actuel, "static") 8 | 9 | app = Flask( 10 | "Application", 11 | template_folder=templates, 12 | static_folder=statics 13 | ) 14 | # On configure la base de données 15 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 16 | # On initie l'extension 17 | db = SQLAlchemy(app) 18 | 19 | from .routes import lieu, accueil, recherche -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | import os 4 | 5 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 6 | templates = os.path.join(chemin_actuel, "templates") 7 | statics = os.path.join(chemin_actuel, "static") 8 | 9 | app = Flask( 10 | "Application", 11 | template_folder=templates, 12 | static_folder=statics 13 | ) 14 | # On configure la base de données 15 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 16 | # On initie l'extension 17 | db = SQLAlchemy(app) 18 | 19 | from .routes import lieu, accueil, recherche -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | import os 4 | 5 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 6 | templates = os.path.join(chemin_actuel, "templates") 7 | statics = os.path.join(chemin_actuel, "static") 8 | 9 | app = Flask( 10 | "Application", 11 | template_folder=templates, 12 | static_folder=statics 13 | ) 14 | # On configure la base de données 15 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 16 | # On initie l'extension 17 | db = SQLAlchemy(app) 18 | 19 | from .routes import lieu, accueil, recherche -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block afternav %} 3 | {% include "partials/recherche.html" %} 4 | {%endblock%} 5 | {% block corps %} 6 |

Bienvenue !

7 | {% if lieux %} 8 |

Il y a {{lieux|length}} lieux enregistrés :

9 | 14 | {% else %} 15 |

La base de données est en cours de constitution

16 | {% endif %} 17 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block afternav %} 3 | {% include "partials/recherche.html" %} 4 | {%endblock%} 5 | {% block corps %} 6 |

Bienvenue !

7 | {% if lieux %} 8 |

{{lieux|length}} derniers lieux enregistrés :

9 | 14 | {% else %} 15 |

La base de données est en cours de constitution

16 | {% endif %} 17 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block afternav %} 3 | {% include "partials/recherche.html" %} 4 | {%endblock%} 5 | {% block corps %} 6 |

Bienvenue !

7 | {% if lieux %} 8 |

{{lieux|length}} derniers lieux enregistrés :

9 | 14 | {% else %} 15 |

La base de données est en cours de constitution

16 | {% endif %} 17 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block afternav %} 3 | {% include "partials/recherche.html" %} 4 | {%endblock%} 5 | {% block corps %} 6 |

Bienvenue !

7 | {% if lieux %} 8 |

{{lieux|length}} derniers lieux enregistrés :

9 | 14 | {% else %} 15 |

La base de données est en cours de constitution

16 | {% endif %} 17 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/accueil.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | {% block afternav %} 3 | {% include "partials/recherche.html" %} 4 | {%endblock%} 5 | {% block corps %} 6 |

Bienvenue !

7 | {% if lieux %} 8 |

{{lieux|length}} derniers lieux enregistrés :

9 | 14 | {% else %} 15 |

La base de données est en cours de constitution

16 | {% endif %} 17 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | 3 | 4 | from .app import app 5 | from .modeles.donnees import Place 6 | 7 | 8 | @app.route("/") 9 | def accueil(): 10 | # On a bien sûr aussi modifié le template pour refléter le changement 11 | lieux = Place.query.all() 12 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 13 | 14 | 15 | @app.route("/place/") 16 | def lieu(place_id): 17 | # On a bien sûr aussi modifié le template pour refléter le changement 18 | unique_lieu = Place.query.get(place_id) 19 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 20 | -------------------------------------------------------------------------------- /cours-flask/exemple7/templates/accueil.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{nom}} 4 | 5 | 6 |

Bienvenue !

7 |

8 | {% if lieux %} 9 | Il y a {{lieux|length}} enregistrés : 10 |

    11 | {% for lieu_id, lieu in lieux.items() %} 12 |
  • {{lieu.nom}}
  • 13 | {% endfor %} 14 |
15 | {% else %} 16 | La base de données est en cours de constitution 17 | {% endif %} 18 |

19 | 20 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | 3 | 4 | from .app import app 5 | from .modeles.donnees import Place 6 | 7 | 8 | @app.route("/") 9 | def accueil(): 10 | # On a bien sûr aussi modifié le template pour refléter le changement 11 | lieux = Place.query.all() 12 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 13 | 14 | 15 | @app.route("/place/") 16 | def lieu(place_id): 17 | # On a bien sûr aussi modifié le template pour refléter le changement 18 | unique_lieu = Place.query.get(place_id) 19 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 20 | -------------------------------------------------------------------------------- /cours-flask/exemple2/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask("Application") 4 | 5 | 6 | @app.route("/") 7 | def index(): 8 | return "Hello world !" 9 | 10 | 11 | @app.route("/places/") 12 | def chemin_place(place_id): 13 | return "On est sur " + place_id 14 | 15 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 16 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 17 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 18 | # Le fichier `script.py` a en __name__ la valeur __main__. 19 | if __name__ == "__main__": 20 | app.run() 21 | -------------------------------------------------------------------------------- /cours-flask/exemple3/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask("Application") 4 | 5 | 6 | @app.route("/") 7 | def index(): 8 | return "Hello world !" 9 | 10 | 11 | @app.route("/places/") 12 | def chemin_place(place_id): 13 | return "On est sur " + str(place_id) 14 | 15 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 16 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 17 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 18 | # Le fichier `script.py` a en __name__ la valeur __main__. 19 | if __name__ == "__main__": 20 | app.run() 21 | -------------------------------------------------------------------------------- /modules_cours/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | from flask_login import LoginManager 4 | import os 5 | from .constantes import SECRET_KEY 6 | 7 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 8 | app = Flask( 9 | "Application" 10 | ) 11 | # On configure le secret 12 | app.config['SECRET_KEY'] = SECRET_KEY 13 | # On configure la base de données 14 | app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://gazetteer_user:password@localhost/gazetteer' 15 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 16 | # On initie l'extension 17 | db = SQLAlchemy(app) 18 | 19 | # On met en place la gestion d'utilisateur-rice-s 20 | login = LoginManager(app) 21 | 22 | -------------------------------------------------------------------------------- /cours-flask/exemple6/templates/place.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gazetteer {%if lieu %}| Lieu : {{lieu.nom}} {% endif %} 4 | 5 | 6 | {% if lieu %} 7 |

{{lieu.nom}}

8 |

{{lieu.moderne}}

9 |
10 |
Longitude
{{lieu.latlong[1]}}
11 |
Latitude
{{lieu.latlong[0]}}
12 |
Description
{{lieu.description}}
13 |
Type
{{lieu.type}}
14 |
15 | {% else %} 16 |

La base de données est en cours de constitution

17 | {% endif %} 18 | 19 | -------------------------------------------------------------------------------- /cours-flask/exemple11/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 | 11 |
12 | 15 |
16 |
17 | {% block corps %}{% endblock %} 18 |
19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /cours-flask/exemple10/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 | 11 |
12 | 15 |
16 |
17 | {% block corps %}{% endblock %} 18 |
19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 | 11 |
12 | 15 |
16 |
17 | {% block corps %}{% endblock %} 18 |
19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 | 11 |
12 | 15 |
16 |
17 | {% block corps %}{% endblock %} 18 |
19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /cours-flask/exemple11/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple8/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.nom}}

10 |

{{lieu.moderne}}

11 |
12 |
Longitude
{{lieu.latlong[1]}}
13 |
Latitude
{{lieu.latlong[0]}}
14 |
Description
{{lieu.description}}
15 |
Type
{{lieu.type}}
16 |
17 | {% else %} 18 |

La base de données est en cours de constitution

19 | {% endif %} 20 |

Retour à l'accueil

21 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple9/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.nom}}

10 |

{{lieu.moderne}}

11 |
12 |
Longitude
{{lieu.latlong[1]}}
13 |
Latitude
{{lieu.latlong[0]}}
14 |
Description
{{lieu.description}}
15 |
Type
{{lieu.type}}
16 |
17 | {% else %} 18 |

La base de données est en cours de constitution

19 | {% endif %} 20 |

Retour à l'accueil

21 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple10/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.nom}}

10 |

{{lieu.moderne}}

11 |
12 |
Longitude
{{lieu.latlong[1]}}
13 |
Latitude
{{lieu.latlong[0]}}
14 |
Description
{{lieu.description}}
15 |
Type
{{lieu.type}}
16 |
17 | {% else %} 18 |

La base de données est en cours de constitution

19 | {% endif %} 20 |

Retour à l'accueil

21 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple12/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-packages/exemple-04/gazetteer/templates/pages/place.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %} 4 | {%if lieu %}| Lieu : {{lieu.place_nom}} {% endif %} 5 | {% endblock %} 6 | 7 | {% block corps %} 8 | {% if lieu %} 9 |

{{lieu.place_nom}}

10 |
11 |
Longitude
{{lieu.place_longitude}}
12 |
Latitude
{{lieu.place_latitude}}
13 |
Description
{{lieu.place_description}}
14 |
Type
{{lieu.place_type}}
15 |
16 | {% else %} 17 |

La base de données est en cours de constitution

18 | {% endif %} 19 |

Retour à l'accueil

20 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple5/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | 6 | @app.route("/") 7 | @app.route("/exemple/") 8 | def accueil(exemple=None): 9 | lieux = [] 10 | if exemple: 11 | lieux = ["Col. Lugdunum", "Augustomagus"] 12 | return render_template("accueil.html", nom="Gazetteer", lieux=lieux) 13 | 14 | 15 | 16 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 17 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 18 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 19 | # Le fichier `script.py` a en __name__ la valeur __main__. 20 | if __name__ == "__main__": 21 | app.run() 22 | -------------------------------------------------------------------------------- /cours-flask/exemple7/templates/place.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gazetteer {%if lieu %}| Lieu : {{lieu.nom}} {% endif %} 4 | 5 | 6 | {% if lieu %} 7 |

{{lieu.nom}}

8 |

{{lieu.moderne}}

9 |
10 |
Longitude
{{lieu.latlong[1]}}
11 |
Latitude
{{lieu.latlong[0]}}
12 |
Description
{{lieu.description}}
13 |
Type
{{lieu.type}}
14 |
15 | {% else %} 16 |

La base de données est en cours de constitution

17 | {% endif %} 18 |

Retour à l'accueil

19 | 20 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/constantes.py: -------------------------------------------------------------------------------- 1 | from warnings import warn 2 | 3 | LIEUX_PAR_PAGE = 2 4 | SECRET_KEY = "JE SUIS UN SECRET !" 5 | API_ROUTE = "/api" 6 | 7 | if SECRET_KEY == "JE SUIS UN SECRET !": 8 | warn("Le secret par défaut n'a pas été changé, vous devriez le faire", Warning) 9 | 10 | 11 | class _TEST: 12 | SECRET_KEY = SECRET_KEY 13 | # On configure la base de données 14 | SQLALCHEMY_DATABASE_URI = 'sqlite:///test_db.sqlite' 15 | SQLALCHEMY_TRACK_MODIFICATIONS = False 16 | 17 | 18 | class _PRODUCTION: 19 | SECRET_KEY = SECRET_KEY 20 | # On configure la base de données 21 | SQLALCHEMY_DATABASE_URI = 'mysql://gazetteer_user:password@localhost/gazetteer' 22 | SQLALCHEMY_TRACK_MODIFICATIONS = False 23 | 24 | CONFIG = { 25 | "test": _TEST, 26 | "production": _PRODUCTION 27 | } -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | from flask_login import LoginManager 4 | import os 5 | from .constantes import SECRET_KEY 6 | 7 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 8 | templates = os.path.join(chemin_actuel, "templates") 9 | statics = os.path.join(chemin_actuel, "static") 10 | 11 | app = Flask( 12 | "Application", 13 | template_folder=templates, 14 | static_folder=statics 15 | ) 16 | # On configure le secret 17 | app.config['SECRET_KEY'] = SECRET_KEY 18 | # On configure la base de données 19 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 20 | # On initie l'extension 21 | db = SQLAlchemy(app) 22 | 23 | # On met en place la gestion d'utilisateur-rice-s 24 | login = LoginManager(app) 25 | 26 | 27 | from . import routes -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | from flask_login import LoginManager 4 | import os 5 | from .constantes import SECRET_KEY 6 | 7 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 8 | templates = os.path.join(chemin_actuel, "templates") 9 | statics = os.path.join(chemin_actuel, "static") 10 | 11 | app = Flask( 12 | "Application", 13 | template_folder=templates, 14 | static_folder=statics 15 | ) 16 | # On configure le secret 17 | app.config['SECRET_KEY'] = SECRET_KEY 18 | # On configure la base de données 19 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 20 | app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 21 | # On initie l'extension 22 | db = SQLAlchemy(app) 23 | 24 | # On met en place la gestion d'utilisateur-rice-s 25 | login = LoginManager(app) 26 | 27 | 28 | from .routes import generic 29 | from .routes import api -------------------------------------------------------------------------------- /data/json/brecht.json: -------------------------------------------------------------------------------- 1 | { 2 | "titre": {"fre": "La Solution", "ger": "Die Lösung"}, 3 | "auteur": "Bertold Brecht", 4 | "annee": 1953, 5 | "source": "https://fr.wikipedia.org/wiki/Die_L%C3%B6sung", 6 | "vers": [ 7 | {"n": 1, "texte": "Après l'insurrection du 17 juin,"}, 8 | {"n": 2, "texte": "Le secrétaire de l'Union des Écrivains"}, 9 | {"n": 3, "texte": "Fit distribuer des tracts dans la Stalinallée."}, 10 | {"n": 4, "texte": "Le peuple, y lisait-on, a par sa faute"}, 11 | {"n": 5, "texte": "Perdu la confiance du gouvernement"}, 12 | {"n": 6, "texte": "Et ce n'est qu'en redoublant d'efforts"}, 13 | {"n": 7, "texte": "Qu'il peut la regagner."}, 14 | {"n": 8, "texte": "Ne serait-il pas"}, 15 | {"n": 9, "texte": "Plus simple alors pour le gouvernement"}, 16 | {"n": 10, "texte": "De dissoudre le peuple"}, 17 | {"n": 11, "texte": "Et d'en élire un autre ?"} 18 | ] 19 | } -------------------------------------------------------------------------------- /data/lanuitdelamort.michel.txt: -------------------------------------------------------------------------------- 1 | Dies irœ, Dies illa 2 | Solvet scelum in favilla. 3 | Jamais ne viendra donc la fin ? 4 | Dorment-ils tous, les meurt-de-faim ? 5 | Jamais, jamais le dernier jour 6 | Ne les jettera-t-il à leur tour 7 | Dans les angoisses de la mort, 8 | Ces bandits que la rage mord ? 9 | 10 | Toujours, esclaves et bourreaux, 11 | Pâtiront-ils leurs échafauds ? 12 | Amis, dans l’ombre entendez-vous 13 | Gronder la mer aux noirs remous ? 14 | Elle monte et les couvrira. 15 | Dies irae, Dies illa... 16 | Elle couvre, pourpre de sang, 17 | L’Elysée et le Vatican. 18 | Compagnons, arrachons nos cœurs, 19 | Ne soyons plus que des vengeurs. 20 | 21 | Passons, effrayants et maudits, 22 | Afin que les maux soient finis. 23 | Comblons l’abîme avec nos corps. 24 | Amis, n’oubliez pas les morts... 25 | La légende des temps nouveaux 26 | Fleurira parmi les tombeaux. 27 | C’est le destin ; le maître est dur. 28 | C’est pourquoi le fer sera pur. 29 | 30 | Dies irae, Dies illa, 31 | Solvet scelum, in favina. 32 | -------------------------------------------------------------------------------- /cours-flask/exemple18/tests/test_user.py: -------------------------------------------------------------------------------- 1 | from .base import Base 2 | from gazetteer.modeles.utilisateurs import User 3 | 4 | 5 | class TestUser(Base): 6 | """ Unit tests for Users """ 7 | def test_creation(self): 8 | with self.app.app_context(): 9 | statut, utilisateur = User.creer("joh", "johanna.johanna@enc-sorbonne.fr", "Johanna", "azerty") 10 | query = User.query.filter(User.user_email == "johanna.johanna@enc-sorbonne.fr").first() 11 | self.assertEqual(query.user_nom, "Johanna") 12 | self.assertEqual(query.user_login, "joh") 13 | self.assertNotEqual(query.user_password, "azerty") 14 | self.assertTrue(statut) 15 | 16 | def test_login_et_creation(self): 17 | with self.app.app_context(): 18 | statut, cree = User.creer("joh", "johanna.johanna@enc-sorbonne.fr", "Johanna", "azerty") 19 | connecte = User.identification("joh", "azerty") 20 | 21 | self.assertEqual(cree, connecte) 22 | self.assertTrue(statut) 23 | -------------------------------------------------------------------------------- /data/Ballade.XXVIII.dePisan.txt: -------------------------------------------------------------------------------- 1 | Mon doulz ami, vueilliez moy pardonner, 2 | Se je ne puis, si tost com je vouldroye, 3 | Parler a vous, car ainçois ordener 4 | Me fault comment sera, ne par quel voye. 5 | Car mesdisans me vont gaitant 6 | Qui du meschief et du mal me font tant, 7 | Que je ne puis joye ne bien avoir, 8 | Pour le desir que j’ay de vous veoir. 9 | 10 | Si pry a Dieu qu’il leur vueille donner 11 | La mort briefment ; car leur vie m’anoye, 12 | Pour ce qu’en dueil me font mes jours finer 13 | Sanz vous veoir, ou est toute ma joye 14 | Car ilz se vont entremettant 15 | De moy gaitier nuit et jour, mais pourtant 16 | Ne vous oubli, ce pouez vous savoir, 17 | Pour le desir que j’ay de vous veoir. 18 | 19 | Mais ne sçaront ja eulx si fort pener, 20 | Que, maugré tous, bien briefment ne vous voie. 21 | Car tant feray, se g’y puis assener, 22 | Que vous verray, quoy qu’avenir m’en doye, 23 | Et vous feray savoir quant. 24 | Mon doulz ami, deportez vous atant. 25 | Car g’y mettray peine, sachiez de voir, 26 | Pour le desir que j’ay de vous veoir. -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | from flask_login import LoginManager 4 | import os 5 | from .constantes import CONFIG 6 | 7 | chemin_actuel = os.path.dirname(os.path.abspath(__file__)) 8 | templates = os.path.join(chemin_actuel, "templates") 9 | statics = os.path.join(chemin_actuel, "static") 10 | 11 | # On initie l'extension 12 | db = SQLAlchemy() 13 | # On met en place la gestion d'utilisateur-rice-s 14 | login = LoginManager() 15 | 16 | app = Flask( 17 | __name__, 18 | template_folder=templates, 19 | static_folder=statics 20 | ) 21 | 22 | 23 | from .routes import generic 24 | from .routes import api 25 | 26 | 27 | def config_app(config_name="test"): 28 | """ Create the application """ 29 | app.config.from_object(CONFIG[config_name]) 30 | 31 | # Set up extensions 32 | db.init_app(app) 33 | # assets_env = Environment(app) 34 | login.init_app(app) 35 | 36 | # Register Jinja template functions 37 | 38 | return app 39 | 40 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 9 | 10 | 11 | 12 | 19 |
20 |
21 |
22 | {% block corps %}{% endblock %} 23 |
24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/connexion.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Connexion{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 | Inscription 24 |
25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/connexion.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Connexion{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 | Inscription 24 |
25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/connexion.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Connexion{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 | Inscription 24 |
25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /supports/chapitre-6/template.omeka.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 19 | 20 | $this)); ?> 21 | 22 |
23 | 24 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /cours-flask/exemple18/tests/test_api.py: -------------------------------------------------------------------------------- 1 | from .base import Base 2 | from json import loads 3 | 4 | 5 | class TestApi(Base): 6 | def test_single_place(self): 7 | """ Vérifie qu'un lieu est bien traité """ 8 | self.insert_all() 9 | response = self.client.get("/api/places/1") 10 | # Le corps de la réponse est dans .data 11 | # .data est en "bytes". Pour convertir des bytes en str, on fait .decode() 12 | content = response.data.decode() 13 | self.assertEqual( 14 | response.headers["Content-Type"], "application/json" 15 | ) 16 | json_parse = loads(content) 17 | self.assertEqual(json_parse["type"], "place") 18 | self.assertEqual( 19 | json_parse["attributes"], 20 | {'name': 'Hippana', 'latitude': 13.4357804, 'longitude': 37.7018481, 'category': 'settlement', 21 | 'description': 'Ancient settlement in the western part of Sicily, probably ' 22 | 'founded in the seventh century B.C.'} 23 | ) 24 | self.assertEqual(json_parse["links"]["self"], 'http://localhost/place/1') 25 | 26 | # On vérifie que le lien est correct 27 | seconde_requete = self.client.get(json_parse["links"]["self"]) 28 | self.assertEqual(seconde_requete.status_code, 200) 29 | -------------------------------------------------------------------------------- /data/scripts/download_pleiades.py: -------------------------------------------------------------------------------- 1 | """ Ce script a pour but de générer un ensemble de données tests pour le cours sur Flask 2 | 3 | Les données originelles sont toutes issues de https://pleiades.stoa.org 4 | 5 | """ 6 | from requests import get 7 | from csv import writer 8 | import os 9 | 10 | 11 | dir_path, _ = os.path.split(os.path.realpath(__file__)) # On utilise la variable nommée "_" par convention 12 | # pour des données d'un tuple que l'on ne veut pas 13 | target_path = os.path.join(dir_path, "..", "csv", "pleiades.csv") 14 | 15 | places_to_retrieve = [462247, 511337, 59687, 187410, 462283, 874299107, 16 | 264408879, 423052, 79368, 599578, 727090, 570180, 138369, 695491849, 589981] 17 | csv_list = [ 18 | ["place_id", "place_nom", "place_description", "place_longitude", "place_latitude", "place_type"] 19 | ] 20 | 21 | for index, place in enumerate(places_to_retrieve): 22 | response = get("https://pleiades.stoa.org/places/{}/json".format(place)) 23 | data = response.json() 24 | lat, long = tuple(data["reprPoint"]) 25 | description = data["description"] 26 | nom = data["title"] 27 | place_type = data["placeTypes"][0] 28 | csv_list.append([index, nom, description, long, lat, place_type]) 29 | 30 | with open(target_path, "w") as f: 31 | csv_writer = writer(f) 32 | for row in csv_list: 33 | csv_writer.writerow(row) 34 | -------------------------------------------------------------------------------- /cours-flask/exemple13/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request 2 | 3 | 4 | from .app import app 5 | from .modeles.donnees import Place 6 | 7 | 8 | @app.route("/") 9 | def accueil(): 10 | # On a bien sûr aussi modifié le template pour refléter le changement 11 | lieux = Place.query.all() 12 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 13 | 14 | 15 | @app.route("/place/") 16 | def lieu(place_id): 17 | # On a bien sûr aussi modifié le template pour refléter le changement 18 | unique_lieu = Place.query.get(place_id) 19 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 20 | 21 | 22 | @app.route("/recherche") 23 | def recherche(): 24 | # On préfèrera l'utilisation de .get() ici 25 | # qui nous permet d'éviter un if long (if "clef" in dictionnaire and dictonnaire["clef"]) 26 | motclef = request.args.get("keyword", None) 27 | # On crée une liste vide de résultat (qui restera vide par défaut 28 | # si on n'a pas de mot clé) 29 | resultats = [] 30 | # On fait de même pour le titre de la page 31 | titre = "Recherche" 32 | if motclef: 33 | resultats = Place.query.filter( 34 | Place.place_nom.like("%{}%".format(motclef)) 35 | ).all() 36 | titre = "Résultat pour la recherche `" + motclef + "`" 37 | return render_template("pages/recherche.html", resultats=resultats, titre=titre) 38 | -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request 2 | 3 | 4 | from .app import app 5 | from .modeles.donnees import Place 6 | 7 | 8 | @app.route("/") 9 | def accueil(): 10 | # On a bien sûr aussi modifié le template pour refléter le changement 11 | lieux = Place.query.all() 12 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 13 | 14 | 15 | @app.route("/place/") 16 | def lieu(place_id): 17 | # On a bien sûr aussi modifié le template pour refléter le changement 18 | unique_lieu = Place.query.get(place_id) 19 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 20 | 21 | 22 | @app.route("/recherche") 23 | def recherche(): 24 | # On préfèrera l'utilisation de .get() ici 25 | # qui nous permet d'éviter un if long (if "clef" in dictionnaire and dictonnaire["clef"]) 26 | motclef = request.args.get("keyword", None) 27 | # On crée une liste vide de résultat (qui restera vide par défaut 28 | # si on n'a pas de mot clé) 29 | resultats = [] 30 | # On fait de même pour le titre de la page 31 | titre = "Recherche" 32 | if motclef: 33 | resultats = Place.query.filter( 34 | Place.place_nom.like("%{}%".format(motclef)) 35 | ).all() 36 | titre = "Résultat pour la recherche `" + motclef + "`" 37 | return render_template("pages/recherche.html", resultats=resultats, titre=titre) 38 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/browse.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Navigation : Page {{resultats.page}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Navigation

8 | {% if resultats %} 9 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

10 | 15 | 38 | {% endif %} 39 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/browse.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Navigation : Page {{resultats.page}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Navigation

8 | {% if resultats %} 9 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

10 | 15 | 38 | {% endif %} 39 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple14/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 18 | 19 | 20 | 21 | 28 | {% block afternav %}{%endblock%} 29 |
30 |
31 |
32 | {% block corps %}{% endblock %} 33 |
34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gazetteer {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 18 | 19 | 20 | 21 | 28 | {% block afternav %}{%endblock%} 29 |
30 |
31 |
32 | {% block corps %}{% endblock %} 33 |
34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 | {% include "partials/recherche.html" %} 8 | 9 |

{{titre}}

10 | {% if resultats %} 11 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

12 | 17 | 41 | {% endif %} 42 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 | {% include "partials/recherche.html" %} 8 | 9 |

{{titre}}

10 | {% if resultats %} 11 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

12 | 17 | 41 | {% endif %} 42 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 | {% include "partials/recherche.html" %} 8 | 9 |

{{titre}}

10 | {% if resultats %} 11 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

12 | 17 | 41 | {% endif %} 42 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/recherche.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| {{titre}}{%endblock%} 4 | 5 | {% block corps %} 6 | 7 | {% include "partials/recherche.html" %} 8 | 9 |

{{titre}}

10 | {% if resultats %} 11 |

Il y a {{resultats.total}} lieux qui répondent à votre requête :

12 | 17 | 41 | {% endif %} 42 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple6/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | lieux = [ 6 | { 7 | "nom": "Col. Lugdunum", 8 | "moderne": "Lyon", 9 | "latlong": [45.762095775, 4.822438025], 10 | "type": "ville", 11 | "description": "Col. Lugdunum was a Roman military colony from 43 BC and a major center in Gaul. Marcus " 12 | "Agrippa was involved in its expansion and two Roman emperors, Claudius and Caracalla, " 13 | "were born there." 14 | }, 15 | { 16 | "nom": "Samarobriva Ambianorum", 17 | "moderne": "Amiens", 18 | "type": "ville", 19 | "description": "An ancient place, cited: BAtlas 11 C3 Samarobriva Ambianorum ", 20 | "latlong": [49.8936075, 2.297948] 21 | } 22 | ] 23 | 24 | 25 | @app.route("/") 26 | def accueil(): 27 | return render_template("accueil.html", nom="Gazetteer", lieux=lieux) 28 | 29 | 30 | @app.route("/place/") 31 | def lieu(place_id): 32 | return render_template("place.html", nom="Gazetteer", lieu=lieux[place_id]) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run() 41 | -------------------------------------------------------------------------------- /cours-flask/exemple7/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | lieux = { 6 | 0: { 7 | "nom": "Col. Lugdunum", 8 | "moderne": "Lyon", 9 | "latlong": [45.762095775, 4.822438025], 10 | "type": "ville", 11 | "description": "Col. Lugdunum was a Roman military colony from 43 BC and a major center in Gaul. Marcus " 12 | "Agrippa was involved in its expansion and two Roman emperors, Claudius and Caracalla, " 13 | "were born there." 14 | }, 15 | 1: { 16 | "nom": "Samarobriva Ambianorum", 17 | "moderne": "Amiens", 18 | "type": "ville", 19 | "description": "An ancient place, cited: BAtlas 11 C3 Samarobriva Ambianorum ", 20 | "latlong": [49.8936075, 2.297948] 21 | } 22 | } 23 | 24 | 25 | @app.route("/") 26 | def accueil(): 27 | return render_template("accueil.html", nom="Gazetteer", lieux=lieux) 28 | 29 | 30 | @app.route("/place/") 31 | def lieu(place_id): 32 | return render_template("place.html", nom="Gazetteer", lieu=lieux[place_id]) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run() 41 | -------------------------------------------------------------------------------- /cours-flask/exemple10/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | lieux = { 6 | 0: { 7 | "nom": "Col. Lugdunum", 8 | "moderne": "Lyon", 9 | "latlong": [45.762095775, 4.822438025], 10 | "type": "ville", 11 | "description": "Col. Lugdunum was a Roman military colony from 43 BC and a major center in Gaul. Marcus " 12 | "Agrippa was involved in its expansion and two Roman emperors, Claudius and Caracalla, " 13 | "were born there." 14 | }, 15 | 1: { 16 | "nom": "Samarobriva Ambianorum", 17 | "moderne": "Amiens", 18 | "type": "ville", 19 | "description": "An ancient place, cited: BAtlas 11 C3 Samarobriva Ambianorum ", 20 | "latlong": [49.8936075, 2.297948] 21 | } 22 | } 23 | 24 | 25 | @app.route("/") 26 | def accueil(): 27 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 28 | 29 | 30 | @app.route("/place/") 31 | def lieu(place_id): 32 | return render_template("pages/place.html", nom="Gazetteer", lieu=lieux[place_id]) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /cours-flask/exemple8/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | lieux = { 6 | 0: { 7 | "nom": "Col. Lugdunum", 8 | "moderne": "Lyon", 9 | "latlong": [45.762095775, 4.822438025], 10 | "type": "ville", 11 | "description": "Col. Lugdunum was a Roman military colony from 43 BC and a major center in Gaul. Marcus " 12 | "Agrippa was involved in its expansion and two Roman emperors, Claudius and Caracalla, " 13 | "were born there." 14 | }, 15 | 1: { 16 | "nom": "Samarobriva Ambianorum", 17 | "moderne": "Amiens", 18 | "type": "ville", 19 | "description": "An ancient place, cited: BAtlas 11 C3 Samarobriva Ambianorum ", 20 | "latlong": [49.8936075, 2.297948] 21 | } 22 | } 23 | 24 | 25 | @app.route("/") 26 | def accueil(): 27 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 28 | 29 | 30 | @app.route("/place/") 31 | def lieu(place_id): 32 | return render_template("pages/place.html", nom="Gazetteer", lieu=lieux[place_id]) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /cours-flask/exemple9/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | 3 | app = Flask("Application") 4 | 5 | lieux = { 6 | 0: { 7 | "nom": "Col. Lugdunum", 8 | "moderne": "Lyon", 9 | "latlong": [45.762095775, 4.822438025], 10 | "type": "ville", 11 | "description": "Col. Lugdunum was a Roman military colony from 43 BC and a major center in Gaul. Marcus " 12 | "Agrippa was involved in its expansion and two Roman emperors, Claudius and Caracalla, " 13 | "were born there." 14 | }, 15 | 1: { 16 | "nom": "Samarobriva Ambianorum", 17 | "moderne": "Amiens", 18 | "type": "ville", 19 | "description": "An ancient place, cited: BAtlas 11 C3 Samarobriva Ambianorum ", 20 | "latlong": [49.8936075, 2.297948] 21 | } 22 | } 23 | 24 | 25 | @app.route("/") 26 | def accueil(): 27 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 28 | 29 | 30 | @app.route("/place/") 31 | def lieu(place_id): 32 | return render_template("pages/place.html", nom="Gazetteer", lieu=lieux[place_id]) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /data/cid.v1071.1682.txt: -------------------------------------------------------------------------------- 1 | Il n'est pas temps encor de chercher le trépas : 2 | Ton prince et ton pays ont besoin de ton bras. 3 | La flotte qu'on craignait, dans ce grand fleuve entrée, 4 | Croit surprendre la ville et piller la contrée. 5 | Les Mores vont descendre, et le flux et la nuit 6 | Dans une heure à nos murs les amène sans bruit. 7 | La Cour est en désordre, et le peuple en alarmes : 8 | On n'entend que des cris, on ne voit que des larmes. 9 | Dans ce malheur public mon bonheur a permis 10 | Que j'ai trouvé chez moi cinq cents de mes amis, 11 | Qui sachant mon affront, poussés d'un même zèle, 12 | Se venaient tous offrir à venger ma querelle. 13 | Tu les as prévenus ; mais leurs vaillantes mains 14 | Se tremperont bien mieux au sang des Africains. 15 | Va marcher à leur tete où l'honneur te demande : 16 | C'est toi que veut pour chef leur généreuse bande. 17 | De ces vieux ennemis va soutenir l'abord : 18 | Là, si tu veux mourir, trouve une belle mort ; 19 | Prends-en l'occasion, puisqu'elle t'est offerte ; 20 | Fais devoir à ton roi son salut à ta perte ; 21 | Mais reviens-en plutôt les palmes sur le front. 22 | Ne borne pas ta gloire à venger un affront ; 23 | Porte-la plus avant : force par ta vaillance 24 | Ce monarque au pardon, et Chimène au silence ; 25 | Si tu l'aimes, apprends que revenir vainqueur, 26 | C'est l'unique moyen de regagner son coeur. 27 | Mais le temps est trop cher pour le perdre en paroles ; 28 | Je t'arrete en discours, et je veux que tu voles. 29 | Viens, suis-moi, va combattre, et montrer à ton roi 30 | Que ce qu'il perd au comte il le recouvre en toi. -------------------------------------------------------------------------------- /cours-flask/exemple11/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from flask_sqlalchemy import SQLAlchemy 3 | 4 | app = Flask("Application") 5 | # On configure la base de données 6 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' 7 | # On initie l'extension 8 | db = SQLAlchemy(app) 9 | 10 | 11 | # On crée notre modèle 12 | class Place(db.Model): 13 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 14 | place_nom = db.Column(db.Text) 15 | place_description = db.Column(db.Text) 16 | place_longitude = db.Column(db.Float) 17 | place_latitude = db.Column(db.Float) 18 | place_type = db.Column(db.String(45)) 19 | 20 | 21 | @app.route("/") 22 | def accueil(): 23 | # On a bien sûr aussi modifié le template pour refléter le changement 24 | lieux = Place.query.all() 25 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 26 | 27 | 28 | @app.route("/place/") 29 | def lieu(place_id): 30 | # On a bien sûr aussi modifié le template pour refléter le changement 31 | unique_lieu = Place.query.get(place_id) 32 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 33 | 34 | 35 | # Ce if permet de vérifier que ce fichier est celui qui est courrament exécuté. Cela permet par exemple d'éviter 36 | # de lancer une fonction quand on importe ce fichier depuis un autre fichier. 37 | # En python, lorsque l'on exécute un script avec la commande `python script.py` 38 | # Le fichier `script.py` a en __name__ la valeur __main__. 39 | if __name__ == "__main__": 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /cours-flask/README.md: -------------------------------------------------------------------------------- 1 | Ce dossier contient des exemples d'application Flask 2 | 3 | 1. [Ma première application Flask : créer une URL](exemple1/app.py) 4 | 2. [Ma première application Flask : créer une route avec paramètre](exemple2/app.py) 5 | 3. [Ma première application Flask : créer une route avec paramètre typé](exemple3/app.py) 6 | 4. [Ma première application Flask : les templates](exemple4/app.py) [Template](exemple4/templates/accueil.html) 7 | 5. [Ma première application Flask : les conditions](exemple5/app.py) [Template](exemple5/templates/accueil.html) 8 | 6. [Ma première application Flask : les dictionnaire](exemple6/app.py) [Template](exemple6/templates/accueil.html) [Template de /place/](exemple6/templates/accueil.html) 9 | 7. [Ma première application Flask : les boucles et les liens ](exemple7/app.py) [Template](exemple7/templates/accueil.html) [Template de /place/](exemple7/templates/accueil.html) 10 | 8. [Ma première application Flask : les conteneurs](exemple8/app.py) [Template Conteneur](exemple8/templates/conteneur.html) [Template Accueil](exemple8/templates/pages/accueil.html) [Template Place](exemple8/templates/pages/place.html) 11 | 9. [Ma première application Flask : les conteneurs avec includes](exemple9/app.py) [Template Conteneur](exemple9/templates/conteneur.html) [Template Metadata](exemple9/templates/partials/metadata.html) [Template Accueil](exemple9/templates/pages/accueil.html) [Template Place](exemple9/templates/pages/place.html) 12 | 9. [Ma première application Flask : les assets](exemple10/app.py) [Static](exemple10/static) [Templates](exemple10/templates) [Template CSS (inclut dans conteneur)](exemple10/templates/partials/css.html) 13 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/pages/inscription.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Inscription{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |

Complétez le formulaire et cliquez sur "S'inscrire".

9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 |
31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/pages/inscription.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Inscription{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |

Complétez le formulaire et cliquez sur "S'inscrire".

9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 |
31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 | {% endblock %} -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/pages/inscription.html: -------------------------------------------------------------------------------- 1 | {% extends "conteneur.html" %} 2 | 3 | {% block titre %}| Inscription{%endblock%} 4 | 5 | {% block corps %} 6 | 7 |

Inscription

8 |

Complétez le formulaire et cliquez sur "S'inscrire".

9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 |
31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 | {% endblock %} -------------------------------------------------------------------------------- /biliopat.csv: -------------------------------------------------------------------------------- 1 | Titre Lien Date 2 | Ouverture des inscriptions aux Journées BiblioPat 2017 http://www.bibliopat.fr/actualite-BiblioPat/ouverture-des-inscriptions-aux-journees-bibliopat-2017 Mon, 25 Sep 2017 14:43:04 +0000 3 | TEAM @BiblioPat_fr : ça gazouille http://www.bibliopat.fr/actualite-BiblioPat/team-bibliopatfr-ca-gazouille Wed, 08 Feb 2017 15:14:34 +0000 4 | Voeux de l'association http://www.bibliopat.fr/actualite-BiblioPat/voeux-de-lassociation Mon, 16 Jan 2017 16:51:02 +0000 5 | "Visites guidées de l'exposition ""Des livres et des lettres"" (Bib. Mazarine)" http://www.bibliopat.fr/actualite-BiblioPat/visites-guidees-de-lexposition-des-livres-et-des-lettres-bib-mazarine Sat, 19 Nov 2016 13:57:53 +0000 6 | Participez aux concours pour les 10 ans de BiblioPat http://www.bibliopat.fr/actualite-BiblioPat/participez-aux-concours-pour-les-10-ans-de-bibliopat Tue, 25 Oct 2016 09:16:23 +0000 7 | Ouverture des inscriptions aux Journées BiblioPat 2016 http://www.bibliopat.fr/actualite-BiblioPat/ouverture-des-inscriptions-aux-journees-bibliopat-2016 Mon, 10 Oct 2016 12:41:54 +0000 8 | Meilleurs voeux 2016 http://www.bibliopat.fr/actualite-BiblioPat/meilleurs-voeux-2016 Fri, 29 Jan 2016 07:15:59 +0000 9 | Journées BiblioPat 2015 en images http://www.bibliopat.fr/actualite-BiblioPat/journees-bibliopat-2015-en-images Fri, 13 Nov 2015 10:12:43 +0000 10 | Fin de l'ouverture des contenus aux abonnés http://www.bibliopat.fr/actualite-BiblioPat/fin-de-louverture-des-contenus-aux-abonnes Thu, 30 Apr 2015 16:40:11 +0000 11 | "Visite guidée de l'exposition ""De l'argile au nuage : une archéologie des catalogues""" http://www.bibliopat.fr/actualite-BiblioPat/visite-guidee-de-lexposition-de-largile-au-nuage-une-archeologie-des-catalogues Tue, 14 Apr 2015 15:05:28 +0000 12 | -------------------------------------------------------------------------------- /data/lettre.louisemichel.txt: -------------------------------------------------------------------------------- 1 | [non daté] 2 | 3 | (Entre le 10 et le 23) octobre 1850 4 | 5 | Monsieur, 6 | 7 | Je ne sais ce que je vous dirai mais je suis au désespoir et il faut que je vous écrive pour souffrir moins. Je ne m’inquiète pas si ma lettre doit vous paraître étrange car vous ne me connaissez pas et tout ce qui me tourmente ne peut vous toucher, mais il faut que je vous le dise pour me calmer un instant. 8 | 9 | Mme Dehamis, ma grand-mère que je ne n’ai jamais quittée, est dangereusement malade et je me trouve sans force et sans courage contre cette affreuse inquiétude. Je suis comme folle, je ne sais ce que je fais ni ce que je dis. L’idée de la perdre est horrible pour moi et je n’en ai pas d’autre. Je vois bien qu’il n’y a plus d’espoir et que tout ce qu’on me dit de rassurant n’est que pour me consoler et cependant, malgré son âge, je ne puis m’imaginer qu’il me soit possible de vivre sans elle. J’oublie presque qu’il me resterait ma mère à consoler. Depuis que je suis au monde, je n’ai jamais quitté mon aïeule. Elle a été ma seule institutrice. Nous ne vivions que l’une pour l’autre et maintenant tout cela va finir. Je ne sais ce que je vous dis. Mes idées se brouillent mais vous me pardonnerez et vous m’écrirez quelques lignes pour me donner un peu de courage car je n’en ai plus. On dit que je suis pieuse, eh bien, si je la perdais, il me semble que je ne croirais plus rien. Dieu serait trop cruel. 10 | 11 | Je trouve sous ma main je ne sais quels brouillons ; je vous les envoie. Ce sont peut-être les derniers que vous recevrez de moi. Si je la perdais, je ne ferais plus rien ou bien cela me ferait mourir. Alors, frère, vous feriez quelques vers sur ma tombe. Adieu, pardon de cette lettre, je suis folle de douleur, je ne sais que devenir, tout me semble mort, écrivez-moi. -------------------------------------------------------------------------------- /cours-flask/exemple15/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request 2 | 3 | 4 | from .app import app 5 | from .modeles.donnees import Place 6 | 7 | 8 | LIEUX_PAR_PAGES = 2 9 | 10 | 11 | @app.route("/") 12 | def accueil(): 13 | # On a bien sûr aussi modifié le template pour refléter le changement 14 | lieux = Place.query.order_by(Place.place_id.desc()).limit(5).all() 15 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 16 | 17 | 18 | @app.route("/place/") 19 | def lieu(place_id): 20 | # On a bien sûr aussi modifié le template pour refléter le changement 21 | unique_lieu = Place.query.get(place_id) 22 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 23 | 24 | 25 | @app.route("/recherche") 26 | def recherche(): 27 | # On préfèrera l'utilisation de .get() ici 28 | # qui nous permet d'éviter un if long (if "clef" in dictionnaire and dictonnaire["clef"]) 29 | motclef = request.args.get("keyword", None) 30 | page = request.args.get("page", 1) 31 | 32 | if isinstance(page, str) and page.isdigit(): 33 | page = int(page) 34 | else: 35 | page = 1 36 | 37 | # On crée une liste vide de résultat (qui restera vide par défaut 38 | # si on n'a pas de mot clé) 39 | resultats = [] 40 | 41 | # On fait de même pour le titre de la page 42 | titre = "Recherche" 43 | if motclef: 44 | resultats = Place.query.filter( 45 | Place.place_nom.like("%{}%".format(motclef)) 46 | ).paginate(page=page, per_page=LIEUX_PAR_PAGES) 47 | titre = "Résultat pour la recherche `" + motclef + "`" 48 | 49 | return render_template( 50 | "pages/recherche.html", 51 | resultats=resultats, 52 | titre=titre, 53 | keyword=motclef 54 | ) 55 | -------------------------------------------------------------------------------- /exercices/Fichiers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Boucles\n", 8 | "\n", 9 | "Sachant que la fonction et les paramètres `glob(\"../data/*.txt\")` dans la première cellule retourne l'ensemble des fichiers disponibles finissant par `*.txt` dans `../data`:\n", 10 | "\n", 11 | "1. Comptez le nombre de chaque mot dans chaque texte\n", 12 | "2. Combien de mots ne sont présents que dans un texte ?" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": null, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "# Exécuter mais ne pas modifier.\n", 22 | "from glob import glob" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "glob(\"../data/*.txt\")" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## De plein texte à TEI\n", 39 | "\n", 40 | "À partir de la variage `text`, créer un fichier `lesdeuxamants.xml` qui soit de la TEI valide. Le corps du texte doit contenir une `div`, un `head`, des `lg`s et des `l`s. Les `l`s seront numérotées via l'attribut `n`." 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "# Exécuter mais ne pas modifier\n", 50 | "with open(\"../data/lesdeuxamants.txt\") as f:\n", 51 | " text = f.read()" 52 | ] 53 | } 54 | ], 55 | "metadata": { 56 | "kernelspec": { 57 | "display_name": "Python 3", 58 | "language": "python", 59 | "name": "python3" 60 | }, 61 | "language_info": { 62 | "codemirror_mode": { 63 | "name": "ipython", 64 | "version": 3 65 | }, 66 | "file_extension": ".py", 67 | "mimetype": "text/x-python", 68 | "name": "python", 69 | "nbconvert_exporter": "python", 70 | "pygments_lexer": "ipython3", 71 | "version": "3.6.9" 72 | } 73 | }, 74 | "nbformat": 4, 75 | "nbformat_minor": 2 76 | } 77 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from flask import url_for 2 | import datetime 3 | 4 | from .. app import db 5 | 6 | 7 | class Authorship(db.Model): 8 | __tablename__ = "authorship" 9 | authorship_id = db.Column(db.Integer, nullable=True, autoincrement=True, primary_key=True) 10 | authorship_place_id = db.Column(db.Integer, db.ForeignKey('place.place_id')) 11 | authorship_user_id = db.Column(db.Integer, db.ForeignKey('user.user_id')) 12 | authorship_date = db.Column(db.DateTime, default=datetime.datetime.utcnow) 13 | user = db.relationship("User", back_populates="authorships") 14 | place = db.relationship("Place", back_populates="authorships") 15 | 16 | def author_to_json(self): 17 | return { 18 | "author": self.user.to_jsonapi_dict(), 19 | "on": self.authorship_date 20 | } 21 | 22 | 23 | # On crée notre modèle 24 | class Place(db.Model): 25 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 26 | place_nom = db.Column(db.Text) 27 | place_description = db.Column(db.Text) 28 | place_longitude = db.Column(db.Float) 29 | place_latitude = db.Column(db.Float) 30 | place_type = db.Column(db.String(45)) 31 | authorships = db.relationship("Authorship", back_populates="place") 32 | 33 | def to_jsonapi_dict(self): 34 | """ It ressembles a little JSON API format but it is not completely compatible 35 | 36 | :return: 37 | """ 38 | return { 39 | "type": "place", 40 | "id": self.place_id, 41 | "attributes": { 42 | "name": self.place_nom, 43 | "description": self.place_description, 44 | "longitude": self.place_longitude, 45 | "latitude": self.place_latitude, 46 | "category": self.place_type 47 | }, 48 | "links": { 49 | "self": url_for("lieu", place_id=self.place_id, _external=True), 50 | "json": url_for("api_places_single", place_id=self.place_id, _external=True) 51 | }, 52 | "relationships": { 53 | "editions": [ 54 | author.author_to_json() 55 | for author in self.authorships 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/modeles/donnees.py: -------------------------------------------------------------------------------- 1 | from flask import url_for 2 | import datetime 3 | 4 | from .. app import db 5 | 6 | 7 | class Authorship(db.Model): 8 | __tablename__ = "authorship" 9 | authorship_id = db.Column(db.Integer, nullable=True, autoincrement=True, primary_key=True) 10 | authorship_place_id = db.Column(db.Integer, db.ForeignKey('place.place_id')) 11 | authorship_user_id = db.Column(db.Integer, db.ForeignKey('user.user_id')) 12 | authorship_date = db.Column(db.DateTime, default=datetime.datetime.utcnow) 13 | user = db.relationship("User", back_populates="authorships") 14 | place = db.relationship("Place", back_populates="authorships") 15 | 16 | def author_to_json(self): 17 | return { 18 | "author": self.user.to_jsonapi_dict(), 19 | "on": self.authorship_date 20 | } 21 | 22 | 23 | # On crée notre modèle 24 | class Place(db.Model): 25 | place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 26 | place_nom = db.Column(db.Text) 27 | place_description = db.Column(db.Text) 28 | place_longitude = db.Column(db.Float) 29 | place_latitude = db.Column(db.Float) 30 | place_type = db.Column(db.String(45)) 31 | authorships = db.relationship("Authorship", back_populates="place") 32 | 33 | def to_jsonapi_dict(self): 34 | """ It ressembles a little JSON API format but it is not completely compatible 35 | 36 | :return: 37 | """ 38 | return { 39 | "type": "place", 40 | "id": self.place_id, 41 | "attributes": { 42 | "name": self.place_nom, 43 | "description": self.place_description, 44 | "longitude": self.place_longitude, 45 | "latitude": self.place_latitude, 46 | "category": self.place_type 47 | }, 48 | "links": { 49 | "self": url_for("lieu", place_id=self.place_id, _external=True), 50 | "json": url_for("api_places_single", place_id=self.place_id, _external=True) 51 | }, 52 | "relationships": { 53 | "editions": [ 54 | author.author_to_json() 55 | for author in self.authorships 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /data/misanthrope.acte3.scene4.txt: -------------------------------------------------------------------------------- 1 | Madame, j'ai beaucoup de grâces à vous rendre : 2 | un tel avis m'oblige, et loin de le mal prendre, 3 | j'en prétends reconnoître, à l'instant, la faveur, 4 | par un avis aussi qui touche votre honneur ; 5 | et comme je vous vois vous montrer mon amie 6 | en m'apprenant les bruits que de moi l'on publie, 7 | je veux suivre, à mon tour, un exemple si doux, 8 | en vous avertissant de ce qu'on dit de vous. 9 | En un lieu, l'autre jour, où je faisois visite, 10 | je trouvai quelques gens d'un très-rare mérite, 11 | qui, parlant des vrais soins d'une âme qui vit bien, 12 | firent tomber sur vous, madame, l'entretien. 13 | Là, votre pruderie et vos éclats de zèle 14 | ne furent pas cités comme un fort bon modèle : 15 | cette affectation d'un grave extérieur, 16 | vos discours éternels de sagesse et d'honneur, 17 | vos mines et vos cris aux ombres d'indécence 18 | que d'un mot ambigu peut avoir l'innocence, 19 | cette hauteur d'estime où vous êtes de vous, 20 | et ces yeux de pitié que vous jetez sur tous, 21 | vos fréquentes leçons, et vos aigres censures 22 | sur des choses qui sont innocentes et pures, 23 | tout cela, si je puis vous parler franchement, 24 | madame, fut blâmé d'un commun sentiment. 25 | à quoi bon, disoient-ils, cette mine modeste, 26 | et ce sage dehors que dément tout le reste ? 27 | Elle est à bien prier exacte au dernier point ; 28 | mais elle bat ses gens, et ne les paye point. 29 | Dans tous les lieux dévots elle étale un grand zèle ; 30 | mais elle met du blanc et veut paroître belle. 31 | Elle fait des tableaux couvrir les nudités ; 32 | mais elle a de l'amour pour les réalités. 33 | Pour moi, contre chacun je pris votre défense, 34 | et leur assurai fort que c'étoit médisance ; 35 | mais tous les sentiments combattirent le mien ; 36 | et leur conclusion fut que vous feriez bien 37 | de prendre moins de soin des actions des autres, 38 | et de vous mettre un peu plus en peine des vôtres ; 39 | qu'on doit se regarder soi-même un fort long temps, 40 | avant que de songer à condamner les gens ; 41 | qu'il faut mettre le poids d'une vie exemplaire 42 | dans les corrections qu'aux autres on veut faire ; 43 | et qu'encor vaut-il mieux s'en remettre, au besoin, 44 | à ceux à qui le ciel en a commis le soin. 45 | Madame, je vous crois aussi trop raisonnable, 46 | pour ne pas prendre bien cet avis profitable, 47 | et pour l'attribuer qu'aux mouvements secrets 48 | d'un zèle qui m'attache à tous vos intérêts. -------------------------------------------------------------------------------- /exercices/CSV.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Exercices CSV\n", 9 | "\n", 10 | "À partir du fichier `data/csv/stages.csv` :\n", 11 | "\n", 12 | "1. Comptez le nombre de stage en France, à l'Étranger.\n", 13 | "2. Quelle est la durée moyenne de stage proposée ?\n", 14 | "3. Classez les livrables (Données\tCahier des charges\tPrototype\tRecommandation\tValorisation) en fonction de leur présence\n", 15 | "4. Faire de même pour les mots-clefs et les technologies\n", 16 | "5. De même pour les institutions\n", 17 | "6. Classez les livrables par type d'institution.\n", 18 | "\n", 19 | "Pour bien profiter de l'exercice, utilisez une cellule par mission.\n", 20 | "\n", 21 | "7. Créer un fichier conservant les classements 3, 4, 5 et 6." 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [] 72 | } 73 | ], 74 | "metadata": { 75 | "kernelspec": { 76 | "display_name": "Python 3", 77 | "language": "python", 78 | "name": "python3" 79 | }, 80 | "language_info": { 81 | "codemirror_mode": { 82 | "name": "ipython", 83 | "version": 3 84 | }, 85 | "file_extension": ".py", 86 | "mimetype": "text/x-python", 87 | "name": "python", 88 | "nbconvert_exporter": "python", 89 | "pygments_lexer": "ipython3", 90 | "version": "3.8.0" 91 | } 92 | }, 93 | "nbformat": 4, 94 | "nbformat_minor": 2 95 | } 96 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/routes/api.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, url_for, jsonify 2 | from urllib.parse import urlencode 3 | 4 | from ..app import app 5 | from ..constantes import LIEUX_PAR_PAGE, API_ROUTE 6 | from ..modeles.donnees import Place 7 | 8 | 9 | def Json_404(): 10 | response = jsonify({"erreur": "Unable to perform the query"}) 11 | response.status_code = 404 12 | return response 13 | 14 | 15 | @app.route(API_ROUTE+"/places/") 16 | def api_places_single(place_id): 17 | try: 18 | query = Place.query.get(place_id) 19 | return jsonify(query.to_jsonapi_dict()) 20 | except: 21 | return Json_404() 22 | 23 | 24 | @app.route(API_ROUTE+"/places") 25 | def api_places_browse(): 26 | """ Route permettant la recherche plein-texte 27 | 28 | On s'inspirera de http://jsonapi.org/ faute de pouvoir trouver temps d'y coller à 100% 29 | """ 30 | # q est très souvent utilisé pour indiquer une capacité de recherche 31 | motclef = request.args.get("q", None) 32 | page = request.args.get("page", 1) 33 | 34 | if isinstance(page, str) and page.isdigit(): 35 | page = int(page) 36 | else: 37 | page = 1 38 | 39 | if motclef: 40 | query = Place.query.filter( 41 | Place.place_nom.like("%{}%".format(motclef)) 42 | ) 43 | else: 44 | query = Place.query 45 | 46 | try: 47 | resultats = query.paginate(page=page, per_page=LIEUX_PAR_PAGE) 48 | except Exception: 49 | return Json_404() 50 | 51 | dict_resultats = { 52 | "links": { 53 | "self": request.url 54 | }, 55 | "data": [ 56 | place.to_jsonapi_dict() 57 | for place in resultats.items 58 | ] 59 | } 60 | 61 | if resultats.has_next: 62 | arguments = { 63 | "page": resultats.next_num 64 | } 65 | if motclef: 66 | arguments["q"] = motclef 67 | dict_resultats["links"]["next"] = url_for("api_places_browse", _external=True)+"?"+urlencode(arguments) 68 | 69 | if resultats.has_prev: 70 | arguments = { 71 | "page": resultats.prev_num 72 | } 73 | if motclef: 74 | arguments["q"] = motclef 75 | dict_resultats["links"]["prev"] = url_for("api_places_browse", _external=True)+"?"+urlencode(arguments) 76 | 77 | response = jsonify(dict_resultats) 78 | return response 79 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/routes/api.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, url_for, jsonify 2 | from urllib.parse import urlencode 3 | 4 | from ..app import app 5 | from ..constantes import LIEUX_PAR_PAGE, API_ROUTE 6 | from ..modeles.donnees import Place 7 | 8 | 9 | def Json_404(): 10 | response = jsonify({"erreur": "Unable to perform the query"}) 11 | response.status_code = 404 12 | return response 13 | 14 | 15 | @app.route(API_ROUTE+"/places/") 16 | def api_places_single(place_id): 17 | try: 18 | query = Place.query.get(place_id) 19 | return jsonify(query.to_jsonapi_dict()) 20 | except: 21 | return Json_404() 22 | 23 | 24 | @app.route(API_ROUTE+"/places") 25 | def api_places_browse(): 26 | """ Route permettant la recherche plein-texte 27 | 28 | On s'inspirera de http://jsonapi.org/ faute de pouvoir trouver temps d'y coller à 100% 29 | """ 30 | # q est très souvent utilisé pour indiquer une capacité de recherche 31 | motclef = request.args.get("q", None) 32 | page = request.args.get("page", 1) 33 | 34 | if isinstance(page, str) and page.isdigit(): 35 | page = int(page) 36 | else: 37 | page = 1 38 | 39 | if motclef: 40 | query = Place.query.filter( 41 | Place.place_nom.like("%{}%".format(motclef)) 42 | ) 43 | else: 44 | query = Place.query 45 | 46 | try: 47 | resultats = query.paginate(page=page, per_page=LIEUX_PAR_PAGE) 48 | except Exception: 49 | return Json_404() 50 | 51 | dict_resultats = { 52 | "links": { 53 | "self": request.url 54 | }, 55 | "data": [ 56 | place.to_jsonapi_dict() 57 | for place in resultats.items 58 | ] 59 | } 60 | 61 | if resultats.has_next: 62 | arguments = { 63 | "page": resultats.next_num 64 | } 65 | if motclef: 66 | arguments["q"] = motclef 67 | dict_resultats["links"]["next"] = url_for("api_places_browse", _external=True)+"?"+urlencode(arguments) 68 | 69 | if resultats.has_prev: 70 | arguments = { 71 | "page": resultats.prev_num 72 | } 73 | if motclef: 74 | arguments["q"] = motclef 75 | dict_resultats["links"]["prev"] = url_for("api_places_browse", _external=True)+"?"+urlencode(arguments) 76 | 77 | response = jsonify(dict_resultats) 78 | return response 79 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Boatlas {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 18 | 19 | 20 | 21 | 43 | {% block afternav %}{%endblock%} 44 |
45 | {% with messages = get_flashed_messages(with_categories=true) %} 46 | {% if messages %} 47 |
48 |
49 | {% for category, message in messages %} 50 | 51 | {% endfor %} 52 |
53 |
54 | {% endif %} 55 | {% endwith %} 56 |
57 |
58 | {% block corps %}{% endblock %} 59 |
60 |
61 |
62 | 63 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Boatlas {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 18 | 19 | 20 | 21 | 46 | {% block afternav %}{%endblock%} 47 |
48 | {% with messages = get_flashed_messages(with_categories=true) %} 49 | {% if messages %} 50 |
51 |
52 | {% for category, message in messages %} 53 | 54 | {% endfor %} 55 |
56 |
57 | {% endif %} 58 | {% endwith %} 59 |
60 |
61 | {% block corps %}{% endblock %} 62 |
63 |
64 |
65 | 66 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/templates/conteneur.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Boatlas {%block titre %}{%endblock%} 6 | {% include "partials/css.html" %} 7 | {% include "partials/metadata.html" %} 8 | 18 | 19 | 20 | 21 | 46 | {% block afternav %}{%endblock%} 47 |
48 | {% with messages = get_flashed_messages(with_categories=true) %} 49 | {% if messages %} 50 |
51 |
52 | {% for category, message in messages %} 53 | 54 | {% endfor %} 55 |
56 |
57 | {% endif %} 58 | {% endwith %} 59 |
60 |
61 | {% block corps %}{% endblock %} 62 |
63 |
64 |
65 | 66 | -------------------------------------------------------------------------------- /data/csv/pleiades.csv: -------------------------------------------------------------------------------- 1 | place_id,place_nom,place_description,place_longitude,place_latitude,place_type 2 | 0,Hippana,"Ancient settlement in the western part of Sicily, probably founded in the seventh century B.C.",37.7018481,13.4357804,settlement 3 | 1,Nicomedia,Nicomedia was founded in 712/11 BC as a Megarian colony named Astacus and was rebuilt by Nicomedes I of Bithynia in 264 BC. The city was an important administrative center of the Roman Empire.,40.7651905,29.919887000000003,settlement 4 | 2,Aornos,"Aornos was a mountain fortress and the site of Alexander the Great's last siege during the winter of 327-6 BC. The ancient site likely corresponds to Ūṇa, a peak on the Pīr-Sar west of the Indus river.",34.75257,72.803461,settlement 5 | 3,"The ""Hochtor Sanctuary""","A Celto-Roman sanctuary situated at an ancient high-mountain pass in the eastern Alps near Grossglockner, excavated beginning in the 1990s. Its ancient name is unknown.",47.081765,12.842636,sanctuary 6 | 4,Lipara (settlement),"A Greek colony and long-time settlement on the island of the same name, located to the north of Sicily in the Tyrrhenian Sea. Modern Lipari.",38.46740105,14.953957299999999,settlement 7 | 5,Arch of Constantine,"The Arch of Constantine at Rome, a triumphal arch dedicated in A.D. 315.",41.889892,12.4904941,arch 8 | 6,Taberna Pomaria di Felix,"A fruit shop in Pompeii (I, 8, 1) with an entrance on to the Via dell'Abbondanza.",40.75074883061887,14.48995445324075,taberna-shop 9 | 7,S. Paulus,"One of Rome's four major papal basilicae, S. Paulus was founded by Constantine I in the early fourth century A.D. and expanded by Valentinian I in the 370s.",41.858695,12.476827,church 10 | 8,Calleva,Calleva Atrebatum (known as Silchester Roman Town) was an Iron Age oppidum and Roman town in Britannia. It was the civitas capital of the Atrebates tribe.,51.35546,-1.0915195,settlement 11 | 9,Colophon/Colophon ad Mare/Notion,A port city founded by Aeolian settlers at the mouth of the River Avci.,37.9928,27.1975,settlement 12 | 10,Bousiris,Bousiris was a city of Lower Egypt near the Phatnitic mouth of the Nile river and was considered one of the possible birthplaces of Osiris.,30.913368,31.238795500000002,settlement 13 | 11,Corinthia,Corinthia was a region of ancient Greece associated with the city-state Corinth.,37.798572,22.834379,region 14 | 12,Garumna (river),The Garonne river is a river of southwestern Gaul and northern Iberia.,44.810025550000006,-0.3184549,river 15 | 13,Caelius Mons,The Caelian Hill in Rome.,41.88755097676503,12.491300775912759,hill 16 | 14,Prinias (Patela),"An Iron Age settlement on the Patela plateau north of the modern village of Prinias; its ancient name is uncertain. The site is notable for its occupation from the end of the Bronze Age through to the Archaic period, as well as for the monumental architecture and Orientalizing sculpture of its Buildings ('Temples') A and B. ",35.168633,25.000922,settlement 17 | -------------------------------------------------------------------------------- /modules_cours/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from werkzeug.security import generate_password_hash, check_password_hash 2 | from flask_login import UserMixin 3 | 4 | from .. app import db, login 5 | 6 | 7 | class User(UserMixin, db.Model): 8 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 9 | user_nom = db.Column(db.Text, nullable=False) 10 | user_login = db.Column(db.String(45), nullable=False, unique=True) 11 | user_email = db.Column(db.Text, nullable=False) 12 | user_password = db.Column(db.String(100), nullable=False) 13 | 14 | @staticmethod 15 | def identification(login, motdepasse): 16 | """ Identifie un utilisateur. Si cela fonctionne, renvoie les données de l'utilisateurs. 17 | 18 | :param login: Login de l'utilisateur 19 | :param motdepasse: Mot de passe envoyé par l'utilisateur 20 | :returns: Si réussite, données de l'utilisateur. Sinon None 21 | :rtype: User or None 22 | """ 23 | utilisateur = User.query.filter(User.user_login == login).first() 24 | if utilisateur and check_password_hash(utilisateur.user_password, motdepasse): 25 | return utilisateur 26 | return None 27 | 28 | @staticmethod 29 | def creer(login, email, nom, motdepasse): 30 | """ Crée un compte utilisateur-rice. Retourne un tuple (booléen, User ou liste). 31 | Si il y a une erreur, la fonction renvoie False suivi d'une liste d'erreur 32 | Sinon, elle renvoie True suivi de la donnée enregistrée 33 | 34 | :param login: Login de l'utilisateur-rice 35 | :param email: Email de l'utilisateur-rice 36 | :param nom: Nom de l'utilisateur-rice 37 | :param motdepasse: Mot de passe de l'utilisateur-rice (Minimum 6 caractères) 38 | 39 | """ 40 | erreurs = [] 41 | if not login: 42 | erreurs.append("Le login fourni est vide") 43 | if not email: 44 | erreurs.append("L'email fourni est vide") 45 | if not nom: 46 | erreurs.append("Le nom fourni est vide") 47 | if not motdepasse or len(motdepasse) < 6: 48 | erreurs.append("Le mot de passe fourni est vide ou trop court") 49 | 50 | # On vérifie que personne n'a utilisé cet email ou ce login 51 | uniques = User.query.filter( 52 | db.or_(User.user_email == email, User.user_login == login) 53 | ).count() 54 | if uniques > 0: 55 | erreurs.append("L'email ou le login sont déjà inscrits dans notre base de données") 56 | 57 | # Si on a au moins une erreur 58 | if len(erreurs) > 0: 59 | return False, erreurs 60 | 61 | # On crée un utilisateur 62 | utilisateur = User( 63 | user_nom=nom, 64 | user_login=login, 65 | user_email=email, 66 | user_password=generate_password_hash(motdepasse) 67 | ) 68 | 69 | try: 70 | # On l'ajoute au transport vers la base de données 71 | db.session.add(utilisateur) 72 | # On envoie le paquet 73 | db.session.commit() 74 | 75 | # On renvoie l'utilisateur 76 | return True, utilisateur 77 | except Exception as erreur: 78 | return False, [str(erreur)] 79 | 80 | def get_id(self): 81 | """ Retourne l'id de l'objet actuellement utilisé 82 | 83 | :returns: ID de l'utilisateur 84 | :rtype: int 85 | """ 86 | return self.user_id 87 | 88 | 89 | @login.user_loader 90 | def trouver_utilisateur_via_id(identifiant): 91 | return User.query.get(int(identifiant)) 92 | -------------------------------------------------------------------------------- /cours-flask/exemple16/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from werkzeug.security import generate_password_hash, check_password_hash 2 | from flask_login import UserMixin 3 | 4 | from .. app import db, login 5 | 6 | 7 | class User(UserMixin, db.Model): 8 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 9 | user_nom = db.Column(db.Text, nullable=False) 10 | user_login = db.Column(db.String(45), nullable=False, unique=True) 11 | user_email = db.Column(db.Text, nullable=False) 12 | user_password = db.Column(db.String(100), nullable=False) 13 | 14 | @staticmethod 15 | def identification(login, motdepasse): 16 | """ Identifie un utilisateur. Si cela fonctionne, renvoie les données de l'utilisateurs. 17 | 18 | :param login: Login de l'utilisateur 19 | :param motdepasse: Mot de passe envoyé par l'utilisateur 20 | :returns: Si réussite, données de l'utilisateur. Sinon None 21 | :rtype: User or None 22 | """ 23 | utilisateur = User.query.filter(User.user_login == login).first() 24 | if utilisateur and check_password_hash(utilisateur.user_password, motdepasse): 25 | return utilisateur 26 | return None 27 | 28 | @staticmethod 29 | def creer(login, email, nom, motdepasse): 30 | """ Crée un compte utilisateur-rice. Retourne un tuple (booléen, User ou liste). 31 | Si il y a une erreur, la fonction renvoie False suivi d'une liste d'erreur 32 | Sinon, elle renvoie True suivi de la donnée enregistrée 33 | 34 | :param login: Login de l'utilisateur-rice 35 | :param email: Email de l'utilisateur-rice 36 | :param nom: Nom de l'utilisateur-rice 37 | :param motdepasse: Mot de passe de l'utilisateur-rice (Minimum 6 caractères) 38 | 39 | """ 40 | erreurs = [] 41 | if not login: 42 | erreurs.append("Le login fourni est vide") 43 | if not email: 44 | erreurs.append("L'email fourni est vide") 45 | if not nom: 46 | erreurs.append("Le nom fourni est vide") 47 | if not motdepasse or len(motdepasse) < 6: 48 | erreurs.append("Le mot de passe fourni est vide ou trop court") 49 | 50 | # On vérifie que personne n'a utilisé cet email ou ce login 51 | uniques = User.query.filter( 52 | db.or_(User.user_email == email, User.user_login == login) 53 | ).count() 54 | if uniques > 0: 55 | erreurs.append("L'email ou le login sont déjà inscrits dans notre base de données") 56 | 57 | # Si on a au moins une erreur 58 | if len(erreurs) > 0: 59 | return False, erreurs 60 | 61 | # On crée un utilisateur 62 | utilisateur = User( 63 | user_nom=nom, 64 | user_login=login, 65 | user_email=email, 66 | user_password=generate_password_hash(motdepasse) 67 | ) 68 | 69 | try: 70 | # On l'ajoute au transport vers la base de données 71 | db.session.add(utilisateur) 72 | # On envoie le paquet 73 | db.session.commit() 74 | 75 | # On renvoie l'utilisateur 76 | return True, utilisateur 77 | except Exception as erreur: 78 | return False, [str(erreur)] 79 | 80 | def get_id(self): 81 | """ Retourne l'id de l'objet actuellement utilisé 82 | 83 | :returns: ID de l'utilisateur 84 | :rtype: int 85 | """ 86 | return self.user_id 87 | 88 | 89 | @login.user_loader 90 | def trouver_utilisateur_via_id(identifiant): 91 | return User.query.get(int(identifiant)) 92 | -------------------------------------------------------------------------------- /exercices/Fonctions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Exercice 1\n", 8 | "\n", 9 | "Créer une fonction qui conjuge un verbe du premier groupe au présent de l'indicatif à la personne demandée telle que:" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "# Vérification\n", 26 | "assert conjugue(\"manger\", 2) == \"manges\"\n", 27 | "assert conjugue(\"balayer\", 5) == \"balayez\"\n", 28 | "assert conjugue(\"travailler\", 3) == \"travaillons\"" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## Exercice 2\n", 36 | "\n", 37 | "Créer une fonction qui conjuge un verbe du premier groupe au temps de l'indicatif demandé (entre présent et imparfait)\n", 38 | "à la personne demandée telle que:" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "# Vérification\n", 55 | "assert conjugue(\"manger\", 2, \"présent\") == \"manges\"\n", 56 | "assert conjugue(\"balayer\", 5, \"présent\") == \"balayez\"\n", 57 | "assert conjugue(\"travailler\", 3, \"imparfait\") == \"travaillions\"" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "## Exercice 3\n", 65 | "\n", 66 | "Créer une fonction qui détermine le verbe, les temps et les personnes possible d'un verbe conjugé au premier groupe, telle que:" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "# Vérification\n", 83 | "assert analyse(\"mange\") == [(\"manger\", 1, \"présent\"), (\"manger\", 3, \"présent\")]\n", 84 | "assert analyse(\"balayez\") == [(\"balayer\", 5, \"présent\")]\n", 85 | "assert analyse(\"travaillions\") == [(\"travailler\", 3, \"imparfait\")]" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "## Exercice 4\n", 93 | "\n", 94 | "Créer une fonction qui pour un fichier texte donné compte le nombre de mots et retourne les 5 mots les plus fréquents." 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "# Vérification\n", 111 | "assert top5(\"../data/Ballade.XXVIII.dePisan.txt\") == [('que', 5), ('de', 5), ('car', 6), ('ne', 7), ('vous', 10)]\n", 112 | "assert top5(\"../data/lettre.louisemichel.txt\") == [('vous', 12), ('ne', 13), ('me', 13), ('que', 15), ('je', 30)]" 113 | ] 114 | } 115 | ], 116 | "metadata": { 117 | "kernelspec": { 118 | "display_name": "Python 3", 119 | "language": "python", 120 | "name": "python3" 121 | }, 122 | "language_info": { 123 | "codemirror_mode": { 124 | "name": "ipython", 125 | "version": 3 126 | }, 127 | "file_extension": ".py", 128 | "mimetype": "text/x-python", 129 | "name": "python", 130 | "nbconvert_exporter": "python", 131 | "pygments_lexer": "ipython3", 132 | "version": "3.6.9" 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 2 137 | } 138 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from werkzeug.security import generate_password_hash, check_password_hash 2 | from flask_login import UserMixin 3 | 4 | from .. app import db, login 5 | 6 | 7 | class User(UserMixin, db.Model): 8 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 9 | user_nom = db.Column(db.Text, nullable=False) 10 | user_login = db.Column(db.String(45), nullable=False, unique=True) 11 | user_email = db.Column(db.Text, nullable=False) 12 | user_password = db.Column(db.String(100), nullable=False) 13 | authorships = db.relationship("Authorship", back_populates="user") 14 | 15 | @staticmethod 16 | def identification(login, motdepasse): 17 | """ Identifie un utilisateur. Si cela fonctionne, renvoie les données de l'utilisateurs. 18 | 19 | :param login: Login de l'utilisateur 20 | :param motdepasse: Mot de passe envoyé par l'utilisateur 21 | :returns: Si réussite, données de l'utilisateur. Sinon None 22 | :rtype: User or None 23 | """ 24 | utilisateur = User.query.filter(User.user_login == login).first() 25 | if utilisateur and check_password_hash(utilisateur.user_password, motdepasse): 26 | return utilisateur 27 | return None 28 | 29 | @staticmethod 30 | def creer(login, email, nom, motdepasse): 31 | """ Crée un compte utilisateur-rice. Retourne un tuple (booléen, User ou liste). 32 | Si il y a une erreur, la fonction renvoie False suivi d'une liste d'erreur 33 | Sinon, elle renvoie True suivi de la donnée enregistrée 34 | 35 | :param login: Login de l'utilisateur-rice 36 | :param email: Email de l'utilisateur-rice 37 | :param nom: Nom de l'utilisateur-rice 38 | :param motdepasse: Mot de passe de l'utilisateur-rice (Minimum 6 caractères) 39 | 40 | """ 41 | erreurs = [] 42 | if not login: 43 | erreurs.append("Le login fourni est vide") 44 | if not email: 45 | erreurs.append("L'email fourni est vide") 46 | if not nom: 47 | erreurs.append("Le nom fourni est vide") 48 | if not motdepasse or len(motdepasse) < 6: 49 | erreurs.append("Le mot de passe fourni est vide ou trop court") 50 | 51 | # On vérifie que personne n'a utilisé cet email ou ce login 52 | uniques = User.query.filter( 53 | db.or_(User.user_email == email, User.user_login == login) 54 | ).count() 55 | if uniques > 0: 56 | erreurs.append("L'email ou le login sont déjà inscrits dans notre base de données") 57 | 58 | # Si on a au moins une erreur 59 | if len(erreurs) > 0: 60 | return False, erreurs 61 | 62 | # On crée un utilisateur 63 | utilisateur = User( 64 | user_nom=nom, 65 | user_login=login, 66 | user_email=email, 67 | user_password=generate_password_hash(motdepasse) 68 | ) 69 | 70 | try: 71 | # On l'ajoute au transport vers la base de données 72 | db.session.add(utilisateur) 73 | # On envoie le paquet 74 | db.session.commit() 75 | 76 | # On renvoie l'utilisateur 77 | return True, utilisateur 78 | except Exception as erreur: 79 | return False, [str(erreur)] 80 | 81 | def get_id(self): 82 | """ Retourne l'id de l'objet actuellement utilisé 83 | 84 | :returns: ID de l'utilisateur 85 | :rtype: int 86 | """ 87 | return self.user_id 88 | 89 | def to_jsonapi_dict(self): 90 | """ It ressembles a little JSON API format but it is not completely compatible 91 | 92 | :return: 93 | """ 94 | return { 95 | "type": "people", 96 | "attributes": { 97 | "name": self.user_nom 98 | } 99 | } 100 | 101 | @login.user_loader 102 | def trouver_utilisateur_via_id(identifiant): 103 | return User.query.get(int(identifiant)) 104 | -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/modeles/utilisateurs.py: -------------------------------------------------------------------------------- 1 | from werkzeug.security import generate_password_hash, check_password_hash 2 | from flask_login import UserMixin 3 | 4 | from .. app import db, login 5 | 6 | 7 | class User(UserMixin, db.Model): 8 | user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True) 9 | user_nom = db.Column(db.Text, nullable=False) 10 | user_login = db.Column(db.String(45), nullable=False, unique=True) 11 | user_email = db.Column(db.Text, nullable=False) 12 | user_password = db.Column(db.String(100), nullable=False) 13 | authorships = db.relationship("Authorship", back_populates="user") 14 | 15 | @staticmethod 16 | def identification(login, motdepasse): 17 | """ Identifie un utilisateur. Si cela fonctionne, renvoie les données de l'utilisateurs. 18 | 19 | :param login: Login de l'utilisateur 20 | :param motdepasse: Mot de passe envoyé par l'utilisateur 21 | :returns: Si réussite, données de l'utilisateur. Sinon None 22 | :rtype: User or None 23 | """ 24 | utilisateur = User.query.filter(User.user_login == login).first() 25 | if utilisateur and check_password_hash(utilisateur.user_password, motdepasse): 26 | return utilisateur 27 | return None 28 | 29 | @staticmethod 30 | def creer(login, email, nom, motdepasse): 31 | """ Crée un compte utilisateur-rice. Retourne un tuple (booléen, User ou liste). 32 | Si il y a une erreur, la fonction renvoie False suivi d'une liste d'erreur 33 | Sinon, elle renvoie True suivi de la donnée enregistrée 34 | 35 | :param login: Login de l'utilisateur-rice 36 | :param email: Email de l'utilisateur-rice 37 | :param nom: Nom de l'utilisateur-rice 38 | :param motdepasse: Mot de passe de l'utilisateur-rice (Minimum 6 caractères) 39 | 40 | """ 41 | erreurs = [] 42 | if not login: 43 | erreurs.append("Le login fourni est vide") 44 | if not email: 45 | erreurs.append("L'email fourni est vide") 46 | if not nom: 47 | erreurs.append("Le nom fourni est vide") 48 | if not motdepasse or len(motdepasse) < 6: 49 | erreurs.append("Le mot de passe fourni est vide ou trop court") 50 | 51 | # On vérifie que personne n'a utilisé cet email ou ce login 52 | uniques = User.query.filter( 53 | db.or_(User.user_email == email, User.user_login == login) 54 | ).count() 55 | if uniques > 0: 56 | erreurs.append("L'email ou le login sont déjà inscrits dans notre base de données") 57 | 58 | # Si on a au moins une erreur 59 | if len(erreurs) > 0: 60 | return False, erreurs 61 | 62 | # On crée un utilisateur 63 | utilisateur = User( 64 | user_nom=nom, 65 | user_login=login, 66 | user_email=email, 67 | user_password=generate_password_hash(motdepasse) 68 | ) 69 | 70 | try: 71 | # On l'ajoute au transport vers la base de données 72 | db.session.add(utilisateur) 73 | # On envoie le paquet 74 | db.session.commit() 75 | 76 | # On renvoie l'utilisateur 77 | return True, utilisateur 78 | except Exception as erreur: 79 | return False, [str(erreur)] 80 | 81 | def get_id(self): 82 | """ Retourne l'id de l'objet actuellement utilisé 83 | 84 | :returns: ID de l'utilisateur 85 | :rtype: int 86 | """ 87 | return self.user_id 88 | 89 | def to_jsonapi_dict(self): 90 | """ It ressembles a little JSON API format but it is not completely compatible 91 | 92 | :return: 93 | """ 94 | return { 95 | "type": "people", 96 | "attributes": { 97 | "name": self.user_nom 98 | } 99 | } 100 | 101 | @login.user_loader 102 | def trouver_utilisateur_via_id(identifiant): 103 | return User.query.get(int(identifiant)) 104 | -------------------------------------------------------------------------------- /cours-flask/exemple17/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, flash, redirect 2 | 3 | 4 | from .app import app, login 5 | from .modeles.donnees import Place 6 | from .modeles.utilisateurs import User 7 | from .constantes import LIEUX_PAR_PAGE 8 | from flask_login import login_user, current_user, logout_user 9 | 10 | 11 | @app.route("/") 12 | def accueil(): 13 | """ Route permettant l'affichage d'une page accueil 14 | """ 15 | # On a bien sûr aussi modifié le template pour refléter le changement 16 | lieux = Place.query.order_by(Place.place_id.desc()).limit(5).all() 17 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 18 | 19 | 20 | @app.route("/place/") 21 | def lieu(place_id): 22 | """ Route permettant l'affichage des données d'un lieu 23 | 24 | :param place_id: Identifiant numérique du lieu 25 | """ 26 | # On a bien sûr aussi modifié le template pour refléter le changement 27 | unique_lieu = Place.query.get(place_id) 28 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 29 | 30 | 31 | @app.route("/recherche") 32 | def recherche(): 33 | """ Route permettant la recherche plein-texte 34 | """ 35 | # On préfèrera l'utilisation de .get() ici 36 | # qui nous permet d'éviter un if long (if "clef" in dictionnaire and dictonnaire["clef"]) 37 | motclef = request.args.get("keyword", None) 38 | page = request.args.get("page", 1) 39 | 40 | if isinstance(page, str) and page.isdigit(): 41 | page = int(page) 42 | else: 43 | page = 1 44 | 45 | # On crée une liste vide de résultat (qui restera vide par défaut 46 | # si on n'a pas de mot clé) 47 | resultats = [] 48 | 49 | # On fait de même pour le titre de la page 50 | titre = "Recherche" 51 | if motclef: 52 | resultats = Place.query.filter( 53 | Place.place_nom.like("%{}%".format(motclef)) 54 | ).paginate(page=page, per_page=LIEUX_PAR_PAGE) 55 | titre = "Résultat pour la recherche `" + motclef + "`" 56 | 57 | return render_template( 58 | "pages/recherche.html", 59 | resultats=resultats, 60 | titre=titre, 61 | keyword=motclef 62 | ) 63 | 64 | 65 | @app.route("/register", methods=["GET", "POST"]) 66 | def inscription(): 67 | """ Route gérant les inscriptions 68 | """ 69 | # Si on est en POST, cela veut dire que le formulaire a été envoyé 70 | if request.method == "POST": 71 | statut, donnees = User.creer( 72 | login=request.form.get("login", None), 73 | email=request.form.get("email", None), 74 | nom=request.form.get("nom", None), 75 | motdepasse=request.form.get("motdepasse", None) 76 | ) 77 | if statut is True: 78 | flash("Enregistrement effectué. Identifiez-vous maintenant", "success") 79 | return redirect("/") 80 | else: 81 | flash("Les erreurs suivantes ont été rencontrées : " + ",".join(donnees), "error") 82 | return render_template("pages/inscription.html") 83 | else: 84 | return render_template("pages/inscription.html") 85 | 86 | 87 | @app.route("/connexion", methods=["POST", "GET"]) 88 | def connexion(): 89 | """ Route gérant les connexions 90 | """ 91 | if current_user.is_authenticated is True: 92 | flash("Vous êtes déjà connecté-e", "info") 93 | return redirect("/") 94 | # Si on est en POST, cela veut dire que le formulaire a été envoyé 95 | if request.method == "POST": 96 | utilisateur = User.identification( 97 | login=request.form.get("login", None), 98 | motdepasse=request.form.get("motdepasse", None) 99 | ) 100 | if utilisateur: 101 | flash("Connexion effectuée", "success") 102 | login_user(utilisateur) 103 | return redirect("/") 104 | else: 105 | flash("Les identifiants n'ont pas été reconnus", "error") 106 | 107 | return render_template("pages/connexion.html") 108 | login.login_view = 'connexion' 109 | 110 | 111 | @app.route("/deconnexion", methods=["POST", "GET"]) 112 | def deconnexion(): 113 | if current_user.is_authenticated is True: 114 | logout_user() 115 | flash("Vous êtes déconnecté-e", "info") 116 | return redirect("/") -------------------------------------------------------------------------------- /cours-flask/exemple18/gazetteer/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, flash, redirect 2 | 3 | 4 | from .app import app, login 5 | from .modeles.donnees import Place 6 | from .modeles.utilisateurs import User 7 | from .constantes import LIEUX_PAR_PAGE 8 | from flask_login import login_user, current_user, logout_user 9 | 10 | 11 | @app.route("/") 12 | def accueil(): 13 | """ Route permettant l'affichage d'une page accueil 14 | """ 15 | # On a bien sûr aussi modifié le template pour refléter le changement 16 | lieux = Place.query.order_by(Place.place_id.desc()).limit(5).all() 17 | return render_template("pages/accueil.html", nom="Gazetteer", lieux=lieux) 18 | 19 | 20 | @app.route("/place/") 21 | def lieu(place_id): 22 | """ Route permettant l'affichage des données d'un lieu 23 | 24 | :param place_id: Identifiant numérique du lieu 25 | """ 26 | # On a bien sûr aussi modifié le template pour refléter le changement 27 | unique_lieu = Place.query.get(place_id) 28 | return render_template("pages/place.html", nom="Gazetteer", lieu=unique_lieu) 29 | 30 | 31 | @app.route("/recherche") 32 | def recherche(): 33 | """ Route permettant la recherche plein-texte 34 | """ 35 | # On préfèrera l'utilisation de .get() ici 36 | # qui nous permet d'éviter un if long (if "clef" in dictionnaire and dictonnaire["clef"]) 37 | motclef = request.args.get("keyword", None) 38 | page = request.args.get("page", 1) 39 | 40 | if isinstance(page, str) and page.isdigit(): 41 | page = int(page) 42 | else: 43 | page = 1 44 | 45 | # On crée une liste vide de résultat (qui restera vide par défaut 46 | # si on n'a pas de mot clé) 47 | resultats = [] 48 | 49 | # On fait de même pour le titre de la page 50 | titre = "Recherche" 51 | if motclef: 52 | resultats = Place.query.filter( 53 | Place.place_nom.like("%{}%".format(motclef)) 54 | ).paginate(page=page, per_page=LIEUX_PAR_PAGE) 55 | titre = "Résultat pour la recherche `" + motclef + "`" 56 | 57 | return render_template( 58 | "pages/recherche.html", 59 | resultats=resultats, 60 | titre=titre, 61 | keyword=motclef 62 | ) 63 | 64 | 65 | @app.route("/register", methods=["GET", "POST"]) 66 | def inscription(): 67 | """ Route gérant les inscriptions 68 | """ 69 | # Si on est en POST, cela veut dire que le formulaire a été envoyé 70 | if request.method == "POST": 71 | statut, donnees = User.creer( 72 | login=request.form.get("login", None), 73 | email=request.form.get("email", None), 74 | nom=request.form.get("nom", None), 75 | motdepasse=request.form.get("motdepasse", None) 76 | ) 77 | if statut is True: 78 | flash("Enregistrement effectué. Identifiez-vous maintenant", "success") 79 | return redirect("/") 80 | else: 81 | flash("Les erreurs suivantes ont été rencontrées : " + ",".join(donnees), "error") 82 | return render_template("pages/inscription.html") 83 | else: 84 | return render_template("pages/inscription.html") 85 | 86 | 87 | @app.route("/connexion", methods=["POST", "GET"]) 88 | def connexion(): 89 | """ Route gérant les connexions 90 | """ 91 | if current_user.is_authenticated is True: 92 | flash("Vous êtes déjà connecté-e", "info") 93 | return redirect("/") 94 | # Si on est en POST, cela veut dire que le formulaire a été envoyé 95 | if request.method == "POST": 96 | utilisateur = User.identification( 97 | login=request.form.get("login", None), 98 | motdepasse=request.form.get("motdepasse", None) 99 | ) 100 | if utilisateur: 101 | flash("Connexion effectuée", "success") 102 | login_user(utilisateur) 103 | return redirect("/") 104 | else: 105 | flash("Les identifiants n'ont pas été reconnus", "error") 106 | 107 | return render_template("pages/connexion.html") 108 | login.login_view = 'connexion' 109 | 110 | 111 | @app.route("/deconnexion", methods=["POST", "GET"]) 112 | def deconnexion(): 113 | if current_user.is_authenticated is True: 114 | logout_user() 115 | flash("Vous êtes déconnecté-e", "info") 116 | return redirect("/") -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction à Python et au développement web avec Python pour les sciences humaines 2 | === 3 | 4 | [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) 5 | 6 | *Tous les contenus originaux sont sous licence CC BY-NC-SA 4.0, les ressources extérieures (comme bootstrap) sont sous leur licence respective* 7 | 8 | 9 | Le langage de programmation Python est souvent utilisé dans les domaines scientifiques aujourd'hui. C’est un langage de programmation relativement accessible et adapté aux universitaires qui travaillent dans le domaine des humanités. Choisir Python s’avère très pertinent quand il s'agit de gérer des données textuelles, très utilisées dans les humanités, mais aussi quand il faut écrire un site web, gérer des données numériques, écrire un script pour faire des transformations, etc. Dans ce cahier virtuel d'exercices, nous vous présenterons le langage et apprendrons les basiques liés à l'algorithmique. Ce livre n'attend de vous aucun prérequis de programmation. 10 | 11 | ## Sources 12 | 13 | - Les chapitres 1 & 2 sont une traduction et adaptation de quatre chapitres de Matt Munson (eux mêmes issus de 10 chapitres écrits par Folgert Karsdorp du KNAW). 14 | - Le chapitre 3 doit être réécrit. 15 | - Les autres chapitres sont des créations. 16 | 17 | Ce document contient l’ensemble des procédures d'installation des logiciels nécessaires pour le cours de python. Si vous êtes bloqués, contactez votre professeur 18 | 19 | ## Sublime text ou PyCharm 20 | 21 | Nous vous recommandons d'installer un bon éditeur de texte voire un bon IDE pour ce cours. Nous vous conseillons [Sublime Text](https://www.sublimetext.com) ou [PyCharm](https://www.jetbrains.com/pycharm) 22 | 23 | Dans ce cours, nous utiliserons un logiciel qui fonctionne très bien avec Firefox et Chrome. Safari fonctionnera aussi, Internet Explorer peut poser des problèmes 24 | 25 | ## Python X ? 26 | 27 | Nous utiserons Python 3 dans notre cours. Les versions précédentes peuvent poser des problèmes. 28 | 29 | 30 | ## Installation 31 | 32 | ### OS X 33 | 34 | **Nous vous conseillons d'installer la distribution Anaconda**. Elle contient tous les modules et packages nécessaires pour ce cours. Elle est disponible pour toutes les plateformes et possède une procédure d'installation assez simple. Vous pouvez la télécharger depuis http://continuum.io/downloads. Des détails pour l'installation peuvent être trouvés ici : http://docs.continuum.io/anaconda/install.html 35 | 36 | Utilisez bien la version 3.6 proposée. Une fois installée, tapez ensuite 37 | 38 | ```shell 39 | conda create -n cours-python 40 | ``` 41 | 42 | suivi de 43 | 44 | ```shell 45 | source activate cours-python 46 | ``` 47 | 48 | Cette dernière active un environnement de python qui nous permet de ne pas modifier l'environnement général de votre ordinateur. 49 | 50 | Allez dans le repository git puis tapez dans le terminal de ce dossier 51 | 52 | ```shell 53 | pip install -r requirements.txt 54 | ``` 55 | 56 | Tapez désormais 57 | 58 | ```shell 59 | jupyter notebook 60 | ``` 61 | 62 | Si tout va bien, cela devrait ouvrir votre navigateur sur la page http://127.0.0.1:8888/ qui s'appelle IP[y]: Notebook. 63 | 64 | ### Linux (Ubuntu/Debian) 65 | 66 | Vous aurez besoin des droits d'administrateurs pour faire ce qui suit. 67 | 68 | Ouvrez un terminal et tapez : 69 | 70 | ```shell 71 | sudo apt-get install python3 libfreetype6-dev python3-pip python3-virtualenv 72 | ``` 73 | 74 | Puis, une fois cela installé, faites : 75 | 76 | ```shell 77 | virtualenv ~/.cours-python -p python3 78 | ``` 79 | Cela créera un environnement virtuel dans lequel nous pourrons installer l'ensemble des informations nécessaires. Allez, dans le terminal, dans le dossier git du cours que vous avez cloné localement et tapez : 80 | 81 | ```shell 82 | source ~/.cours-python/bin/activate 83 | ``` 84 | 85 | Cette commande sera obligatoire à chaque fois que vous voudrez travailler avec le cours. Dans le même terminal, tapez maintenant 86 | 87 | ```shell 88 | pip install -r requirements.txt 89 | ``` 90 | 91 | Cela installera les packages nécessaires pour le cours. Une fois ces packages installés, il suffira de taper 92 | 93 | ```shell 94 | jupyter notebook 95 | ``` 96 | 97 | Si tout va bien, cela devrait ouvrir votre navigateur sur la page http://127.0.0.1:8888/ qui s'appelle IP[y]: Notebook. 98 | 99 | ## Contributeurs 100 | 101 | - Mike Kestemont 102 | - Folgert Karsdorp 103 | - Maarten van Gompel 104 | - Matt Munson 105 | - Thibault Clérice 106 | 107 | ## Ressources supplémentaires 108 | - http://flask.pocoo.org/docs/0.12/deploying/mod_wsgi/ 109 | -------------------------------------------------------------------------------- /Chapitre 12 - Jointures SQL et Update - Exercice Jointure.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Chapitre 11 - Jointures SQL et Update - Exercice Jointure\n", 8 | "===" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "# On remet en place la configuration Flask / MySQL\n", 18 | "\n", 19 | "from flask import Flask\n", 20 | "from flask_sqlalchemy import SQLAlchemy\n", 21 | "\n", 22 | "app = Flask(\"Nom\")\n", 23 | "app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///cours-flask/db.sqlite'\n", 24 | "app.config[\"SQLALCHEMY_TRACK_MODIFICATIONS\"] = False\n", 25 | "db = SQLAlchemy(app)" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "Complétez le code ci-dessous pour ajouter une relation entre les noms de lieu et et les lieux en utilisant le schéma ci-dessous :\n", 33 | "\n", 34 | "\n", 35 | "![Modele](images/datamodel.png)\n", 36 | "\n" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "import datetime\n", 46 | "\n", 47 | "\n", 48 | "class Authorship(db.Model):\n", 49 | " __tablename__ = \"authorship\"\n", 50 | " authorship_id = db.Column(db.Integer, nullable=True, autoincrement=True, primary_key=True)\n", 51 | " authorship_place_id = db.Column(db.Integer, db.ForeignKey('place.place_id'))\n", 52 | " authorship_user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'))\n", 53 | " authorship_date = db.Column(db.DateTime, default=datetime.datetime.utcnow)\n", 54 | " user = db.relationship(\"User\", back_populates=\"authorships\")\n", 55 | " place = db.relationship(\"Place\", back_populates=\"authorships\")\n", 56 | "\n", 57 | "class User(db.Model):\n", 58 | " user_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True)\n", 59 | " user_nom = db.Column(db.Text, nullable=False)\n", 60 | " user_login = db.Column(db.String(45), nullable=False, unique=True)\n", 61 | " user_email = db.Column(db.Text, nullable=False)\n", 62 | " user_password = db.Column(db.String(100), nullable=False)\n", 63 | " authorships = db.relationship(\"Authorship\", back_populates=\"user\")\n", 64 | " \n", 65 | "class Place(db.Model):\n", 66 | " place_id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True)\n", 67 | " place_nom = db.Column(db.Text)\n", 68 | " place_description = db.Column(db.Text)\n", 69 | " place_longitude = db.Column(db.Float)\n", 70 | " place_latitude = db.Column(db.Float)\n", 71 | " place_type = db.Column(db.String(45))\n", 72 | " authorships = db.relationship(\"Authorship\", back_populates=\"place\")\n", 73 | " # A compléter ?\n", 74 | " \n", 75 | " \n", 76 | "class Variante(db.Model):\n", 77 | " # A compléter\n", 78 | " variante_id\n", 79 | " variante_nom\n", 80 | " variante_lang_code\n", 81 | " variante_place_id" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "place = Place.query.get(13)\n", 91 | "print(place.place_nom)\n", 92 | "# Executer l'insertion une seule fois\n", 93 | "if Variante.query.count() == 0:\n", 94 | " place.variantes_nom.append(Variante(variante_nom=\"Garonne\", variante_lang_code=\"fre\"))\n", 95 | " place.variantes_nom.append(Variante(variante_nom=\"Garona\", variante_lang_code=\"esp\"))\n", 96 | " db.session.add(place)\n", 97 | " db.session.commit()\n", 98 | "# Cette ligne affiche \"Garonne\"\n", 99 | "print(Variante.query.get(1).variante_nom)\n", 100 | "# Cette ligne affiche ['Garonne', 'Garona']\n", 101 | "print([v.variante_nom for v in place.query.get(13).variantes_nom])" 102 | ] 103 | } 104 | ], 105 | "metadata": { 106 | "kernelspec": { 107 | "display_name": "Python 3", 108 | "language": "python", 109 | "name": "python3" 110 | }, 111 | "language_info": { 112 | "codemirror_mode": { 113 | "name": "ipython", 114 | "version": 3 115 | }, 116 | "file_extension": ".py", 117 | "mimetype": "text/x-python", 118 | "name": "python", 119 | "nbconvert_exporter": "python", 120 | "pygments_lexer": "ipython3", 121 | "version": "3.6.7" 122 | } 123 | }, 124 | "nbformat": 4, 125 | "nbformat_minor": 2 126 | } 127 | --------------------------------------------------------------------------------