Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 2021 du devoir python intitulé Phototheque_Django_Reinhardt #1

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion Documentation/DjangoPhoto_app.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
---destinée à la réalisation de l'application Python pour la fin du module
---dispensé aux M2-TNAH par Thibault CLérice

BEGIN TRANSACTION;

CREATE TABLE IF NOT EXISTS `user` (
`user_id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`user_nom` TINYTEXT NOT NULL,
`user_prenom` TINYTEXT NOT NULL,
`user_login` VARCHAR ( 45 ) NOT NULL,
`user_email` TINYTEXT NOT NULL,
`user_motdepasse` VARCHAR ( 100 ) NOT NULL,
`user_type` TEXT DEFAULT 'user'
);

DROP TABLE IF EXISTS `authorship`;
CREATE TABLE IF NOT EXISTS `authorship` (
`authorship_id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`authorship_user_id` integer NOT NULL,
`authorship_image_id` integer NOT NULL,
`authorship_date` DATETIME DEFAULT current_timestamp,
FOREIGN KEY(authorship_user_id) REFERENCES user(user_id),
FOREIGN KEY(authorship_image_id) REFERENCES image(id)
);

CREATE TABLE IF NOT EXISTS Image (
id INTEGER PRIMARY KEY AUTOINCREMENT,
titre TEXT NOT NULL,
Expand All @@ -11,9 +33,41 @@ CREATE TABLE IF NOT EXISTS Image (
description TEXT NOT NULL,
source TEXT NOT NULL,
tag TEXT NOT NULL,
orientation TEXT NOT NULL
orientation TEXT NOT NULL,
image_valid TINYTEXT DEFAULT 'y',
img_user_id INTEGER
);

CREATE TABLE IF NOT EXISTS tag_img (
tag_mot TEXT NOT NULL PRIMARY KEY
);

INSERT INTO `tag` (
`tag_mot`)
VALUES
("quintette"),
("musicien"),
("famille"),
("portrait"),
("autre")
;

CREATE TABLE IF NOT EXISTS orientation_img (
orientation_type TEXT NOT NULL PRIMARY KEY
);

INSERT INTO `orientation` (
`orientation_type`)
VALUES
("portrait"),
("paysage")
;


COMMIT;

BEGIN TRANSACTION;

INSERT or IGNORE INTO Image (titre, chemin, date, nom_photographe,description,source,tag,orientation) VALUES ('Django en famille', '<img src="/static/img/002.jpg">', 'circa 1920','', 'Django en famille. De gauche à droite : sa mère, dite Negros (la deuxième), Django (le septième).', 'BnF / Fonds Ch. Delaunay, Boîte 71, page 3', 'famille', 'paysage');
INSERT or IGNORE INTO Image (titre, chemin, date, nom_photographe,description,source,tag,orientation) VALUES ('Django adolescent au banjo', '<img src="/static/img/003.jpg">', 'circa 1923','', 'Django adolescent au banjo. ', 'BnF / Fonds Ch. Delaunay, Boîte 71, page 4', 'banjo', 'portrait');
INSERT or IGNORE INTO Image (titre, chemin, date, nom_photographe,description,source,tag,orientation) VALUES ('Django adolescent avec un Borsalino', '<img src="/static/img/004.jpg">', 'circa 1931','', 'Django adolescent avec un Borsalino.', 'BnF / Fonds Ch. Delaunay, Boîte 71, page 5', 'adolescent', 'portrait');
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
Est une application web réalisée dans le cadre des enseignements (``CSS``, ``HTML``, ``Python`` et ``SQL``) pour le Master 2 en Technologies numériques appliquées à l'histoire, promotion 2019-2020, à l'Ecole nationale des chartes.

## Présentation du projet
L'application vise à présenter un corpus composé de 22 photographies de Django Reinhardt retraçant la vie du guitariste.
L'application vise à présenter un corpus composé d'une vingtaine de photographies de Django Reinhardt retraçant la vie du guitariste.
A partir d'une base de données ``SQLite``, le projet est développé en ``Python 3`` et utilise ``Bootstrap`` pour la mise en forme graphique.

* Une galerie globale du corpus permet donc le renvoi à partir du titre de chaque photographie sur une notice décrivant le document et présentant également le nom du photographe et sa source.
* La recherche s'effectue par mots-clefs (famille, portrait, musicien, quintette), par nom du photographe, par date, par l'orientation de l'image (portrait/paysage), ou en accès direct via la Galerie.
* Une biographie de l'auteur est proposée avec des liens vers des sources.
* Avec la création d'un compte, l'utilisateur peut enrichir la photothèque en créant une notice et téléchargeant une image. Après être connecté, l'utilisateur pourra modifier sa notice ou supprimer son image. L'utilisateur ne peut modifier que les images de son compte.

## Son installation
### :penguin: Linux
Expand Down
File renamed without changes.
97 changes: 97 additions & 0 deletions commentaire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
## Phase d'installation

- `git init` inutile
- `MySLQ` inutile?
- Erreur: se déplacer dans `./projetDangoPhoto` et non `~/`

## Lancement

- Le premier lancement ne fonctionne pas: la fonction `secure_filename` ne fonctionne pas car mauvaise version de Werkzeug
- Bug connu il y a 17 mois: donc pas de tentative de réinstallation avant soumission
https://stackoverflow.com/questions/61628503/flask-uploads-importerror-cannot-import-name-secure-filename

## Hygiène du code

- Problème d'indentation ici et là (exemple: fichier donnees.py, ligne 77-86)
- 2 fichiers inutiles dans routes (api et generic.py)
- Les noms de variables: éviter les noms commençant par des majuscules pour les instances: il faut réserver cela aux classes
- Les imports dans `routes/__init__.py` sont illogiques ou répétés, proposition de correction:

```python
from djangophoto.app import app, login, db
from djangophoto.modeles.donnees import Orientation_img, Tag_img, Image, Authorship
from djangophoto.modeles.utilisateurs import User
from djangophoto.utils import lenTitle, lenDesc, extension_ok
from djangophoto.constantes import DOSSIER_UPLOAD
```

## Modeles

Note générale:

Une seule table est véritablement modifiable: celle des photos. Il n'y a aucune gestion dynamique des mots clefs, des photographes... Un mot clef n'est pas un mot-clef s'il est "unique": c'est une catégorie.
On regrette donc la très faible utilisation du moteur relationnel et de ses capacités.

### Partie SQL

- La table `Orientation_img` est inutile: elle ne fournit aucune fonctionnalité qu'un champ ne pourrait pas offrir
- La table `Tag_img` n'est pas réellement utilisée, dans la mesure où sa clef primaire est aussi sa seule valeur. Par ailleurs, on attend, pour un système de `tags`, d'avoir une relation N-to-N
- La date en `integer` est probablement une erreur mais pose problème
- Le champ image_valid n'est jamais utilisé.

### Partie Python

- La fonction get_id ne sert à rien.
- `return` ne prend pas de parenthèse (fonction `get_id()`)

### Mixte

- Il n'est pas normal de sauvegarder un tag HTML là où un chemin aurait suffit (Image.chemin), forçant à des bidouillages (`deleteImg.chemin [21:-14]`)
- Vu la situation, le nom du fichier aurait suffit (083.jpg): sauvegarder le nom complet du fichier pose un problème pour des maintenances futures (changement de dossier par exemple)
- La mise à jour de l'imag ede permet pas de changer l'image
- Où est utilisé paysage vs. portrait ?

## Fonctionnalités

- Pas de pagination
- Pas de possibilité de mise à jour des images
- Moteur de recherche "simple"
- La page `liste` n'utilise pas `Authorship`. Dans cette même page, la fonction `group_by` ne fait pas sens car des personnes peuvent partager le même nom de famille.


## Code

- Les lignes 204-206 ne servent à rien dans `routes/__init__.py` car elles ne peuvent pas être atteintes
- Le carousel n'est pas dynamique: si je supprime les images, il ne marche plus
- Dans le HTML, il reste des liens qui n'utilisent pas `url_for` (biographie.html)
- Vous pourriez simplifier:

```python
{% for clef in tag_img %}
{% if clef.tag_mot == updateImg.tag %}
<option value="{{clef.tag_mot}}" selected>{{clef.tag_mot}}</option>
{% else %}
<option value="{{clef.tag_mot}}">{{clef.tag_mot}}</option>
{% endif %}
{% endfor %}

```

en
```python
{% for clef in tag_img %}
<option value="{{clef.tag_mot}}" {% if clef.tag_mot == updateImg.tag %} selected {%endif}>{{clef.tag_mot}}</option>
{% endfor %}

```
- Votre bouton ligne 87 dans update-image n'est pas dans sa colonne.

# Notes

## Note SQL : 9

Vous ne faites pas vraiment usage des possibilités de SQL et le modèle pose quelques problèmes (y compris quand on voit en base ensuite des valeurs non numériques dans des champs numériques).

## Note python: 7.5

Des progrès, mais encore loin de ce qui était attendu: vous restez à la surface des possibles et ne remplissez pas la feuille de route que nous avions établi, à savoir produire une véritable application qui mette en valeurs vos compétences.
Binary file removed projet_DjangoPhoto/app/__pycache__/app.cpython-36.pyc
Binary file not shown.
Binary file not shown.
16 changes: 0 additions & 16 deletions projet_DjangoPhoto/app/modeles/donnees.py

This file was deleted.

90 changes: 0 additions & 90 deletions projet_DjangoPhoto/app/routes.py

This file was deleted.

43 changes: 0 additions & 43 deletions projet_DjangoPhoto/app/templates/containeur.html

This file was deleted.

Binary file modified projet_DjangoPhoto/db_DjangoPhoto.sqlite
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#import des packages
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
import os
import os.path
from .constantes import SECRET_KEY
from .constantes import DOSSIER_UPLOAD

#Stockage des chemins courants
chemin_actuel = os.path.dirname(os.path.abspath(__file__))
#Stockage des chemins vers les "templates"
templates = os.path.join(chemin_actuel, "templates")
#Stockage des chemins vers les "static"
statics = os.path.join(chemin_actuel, "static")
# on stocke le chemin vers le dossier où stocker les images téléchargées
uploads = os.path.join(chemin_actuel, "img")


#On paramètre l'application web
app = Flask(
Expand All @@ -18,11 +23,16 @@
static_folder=statics
)

# On configure le secret
app.config['SECRET_KEY'] = SECRET_KEY
#On configure la base de données
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///./db_DjangoPhoto.sqlite'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

#On initie l'extension
db = SQLAlchemy(app)

from .routes import accueil, biographie, galerie, a_propos, img, recherche
# On met en place la gestion d'utilisateur-rice-s
login = LoginManager(app)

import djangophoto.routes
16 changes: 16 additions & 0 deletions projet_DjangoPhoto/djangophoto/constantes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from warnings import warn

# Déclaration de toutes les constantes à utiliser dans le projet
# Convention : les constantes portent des noms en majuscule

RESULTATS_PAR_PAGE = 6
# variable qui définit le nombre de résultats par page (utilisée pour l'index et la recherche simple)
DOSSIER_UPLOAD = "./djangophoto/static/img/"

SECRET_KEY = "JE SUIS UN SECRET !"
# variable utilisée comme clé cryptographique, qui permet de générer des signatures ou tokens

if SECRET_KEY == "JE SUIS UN SECRET !":
warn("Le secret par défaut n'a pas été changé, vous devriez le faire", Warning)


Empty file.
Binary file not shown.
Binary file not shown.
Loading