5a. Base de données - Yolino/t211-dbox-fm GitHub Wiki

Résumé coaching 5.a

+ Qu'avez vous comme données dans la base de données ? Quel est le format ?
+ Comment enregistrez-vous les données ? A la main ? Avec l'application ? Avec le projet d'électronique ?
+ Comment récupérez-vous les données 

1. Les données dans la base de données

Voici une représentation de la structure de notre base de données PostgreSQL. Ces images ont été générées sur base d'un dump de la base de données qui a été importé sur le site https://dbdiagram.io. Notons ici que la structure est scindée en deux captures d'écran pour plus de visibillité. La première partie affiche les tables créées automatiquement pour la gesion des structures built-in de Django, et la seconde concerne nos propres structures créées grâce à l'ORM de Django dans les fichiers nommés models.py (voir /backend/*/models.py). La table auth_user est représentée deux fois pour permettre une meilleure compréhension des relations qui orbitent amplement autour de cette dernière.

db1

Django dispose d'un système de gestion des utilisateurs qui implémente les attributs évidents (username, password, email, ...), mais également des structures permettant une gestion fine des permissions, et la possibilité de leur distribution à plus grande échelle grâce à des groupes. C'est notamment ce que nous mettons en place avec le groupe Moderators qui autorise chacun de ses membres à voir le contenu banni et effectuer des opérations de modifications sur les avertissements (bannir ou libérer le contenu). Les actions des administrateurs sont également loggées dans une table. On retrouve deux entités orphelines : django_session qui maintient l'état des sessions des utilisateurs après l'authentification, et django_migrations qui trace les changements de structures effectués par l'ORM de Django lors de l'application sur la base de données d'une modification des fichiers models.py.

db2

Les structures propres à notre backend sont réparties en plusieurs applications Django, nommées content, moderation et live. Chaque application apporte ses propres tables, et on trouve dans leurs noms le préfixe de l'application. La structure principale est la table des publications, qui permet aux utilisateurs de poster des fichiers audio. Notons que les images de couverture ainsi que les audios sont stockés sur le File System du conteneur backend et non dans la base de données, ce qui aurait été trop volumineux et peu rentable, surtout avec la présence des champs ImageField et FileField de Django pour automatiser leur gestion indépendante.

D'autres tables permettent de suivre les réactions aux publications, telles que le visionnage, les commentaires, les votes (upvote/downvote). Notons ici que nous introduisons une redondance entre les Views/Votes et les attributs view_count/vote_count de Publication. La raison est que s'il fallait récupérer toutes les entrées de la table annexe pour en récupérer les statistiques de vues et de votes, cela aurait été très peu efficient. Nous avons donc dédoublé cette information pour une plus grande efficacité de l'application, en leur imposant des contraintes pour assurer la cohérence et l'actualisation des attributs d'une publication lors d'ajout de lignes dans les tables de référence.

L'application moderation met en place plusieurs tables permettant de traquer les avertissements de contenu ainsi que leur état. Quant à live, son unique table garde un suivi du programme de la station radio.

2. Enregistrement de données

Pour écrire dans la base de données, le traitement d'une requête liée à l'API initialise dynamiquement une instance d'une classe avec ses attributs, et nous l'engistrons avec sa méthode built-in save(), qui effectuera l'insertion. Voici un exemple issu de content/schema.py :

publication = Publication(title=title, cover=cover, tag=tag,description=description, audio=audio,author=author)
publication.save()

3. Récupération de données

Les lectures sont également effectuées par le biais de la classe Python, et appelées par les différentes requêtes reçues par l'API. Nous pouvons utiliser à cet effet la propriété objects de ces classes, et potentiellement les trier, les ordonner, et effectuer d'autres traitements. Voici un exemple issu de content/schema.py :

result = Publication.objects.select_related("author")
result = result.filter(author__username__iexact=author)
result = result.order_by(order_by)
return result

4. Informations complémentaires

La connexion à la base de données est effectuée par le backend vers le conteneur approprié. Elle emploie un utilisateur disposant du minimum nécessaire de privilèges afin de limiter les risques liés à une utilisation malveillante de l'API :

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': get_secret("db_name"),
        'USER': 'django',
        'PASSWORD': get_secret("db_django_password"),
        'HOST': 'db', # Refers to the 'db' container name from compose.yaml
        'PORT': 5432,
    }
}