Site icon Blog ARC Optimizer

Modèles, administrateur et exploitation de la base de données relationnelle (partie 3)


À propos de l'auteur

Philip Kiely est développeur, écrivain et entrepreneur. Il est étudiant au Grinnell College (promotion 2020).
En savoir plus sur
Philip
Kiely

Le panneau d'administration est l'une des fonctionnalités les plus puissantes et les plus flexibles fournies par le framework Web Django, combinant des fonctionnalités instantanées standard avec une personnalisation infinie. En utilisant un exemple de projet basé sur un système d'inventaire de bibliothèque, nous utiliserons le panneau d'administration pour en savoir plus sur la création de modèles et l'interaction avec des bases de données relationnelles dans Django.

Avant de commencer, je tiens à noter que les capacités administratives intégrées de Django , même après personnalisation, ne sont pas destinés aux utilisateurs finaux. Le panneau d'administration existe en tant qu'outil de développement, d'opérateur et d'administrateur pour créer et gérer des logiciels. Il n'est pas destiné à être utilisé pour donner aux utilisateurs finaux des capacités de modération ou toute autre capacité d'administrateur sur la plate-forme que vous développez.

Cet article est basé sur une hypothèse en deux parties:

  1. Le panneau d'administration de Django est si intuitif que vous savez déjà comment l'utiliser.
  2. Le panneau d'administration de Django est si puissant que nous pouvons l'utiliser comme un outil pour apprendre à représenter des données dans une base de données relationnelle à l'aide d'un modèle Django.

J'offre ces idées avec le avertir que nous aurons encore besoin d'écrire du code de configuration pour activer les capacités plus puissantes du panneau d'administration, et nous devrons toujours utiliser l'ORM basé sur des modèles de Django (mapping objet-relationnel) pour spécifier la représentation des données dans notre système. [19659009] Configuration

Nous allons travailler avec un exemple de projet dans cet article. Le projet modélise certaines données qu'une bibliothèque pourrait stocker sur ses livres et ses mécènes. L'exemple devrait être assez applicable à de nombreux types de systèmes qui gèrent les utilisateurs et / ou l'inventaire. Voici un aperçu de l'apparence des données:

Modèle de données. ( Grand aperçu )

Veuillez exécuter les étapes suivantes pour exécuter l'exemple de code sur votre machine locale.

1. Installation de packages

Avec Python 3.6 ou supérieur installé, créez un répertoire et un environnement virtuel. Ensuite, installez les packages suivants:

 pip install django django-grappelli 

Django est le cadre Web avec lequel nous travaillons dans cet article. ( django-grappelli est un thème de panneau d'administration que nous aborderons brièvement.)

2. Obtenir le projet

Avec les packages précédents installés, téléchargez l'exemple de code depuis GitHub. Exécuter:

 git clone https://github.com/philipkiely/library_records.git
cd library_records / library 

3. Création d'un superutilisateur

À l'aide des commandes suivantes, configurez votre base de données et créez un superutilisateur. L'interface de ligne de commande vous guidera à travers le processus de création d'un superutilisateur. Votre compte de superutilisateur vous permettra d'accéder au panneau d'administration dans un instant, alors n'oubliez pas le mot de passe que vous avez défini. Utilisation:

 python manage.py migrate
python manage.py crée un superutilisateur 

4. Chargement des données

Pour notre exploration, j'ai créé un ensemble de données appelé un appareil que vous pouvez charger dans la base de données (plus sur la façon de créer un appareil à la fin de l'article). Utilisez le luminaire pour remplir votre base de données avant de l'explorer dans le panneau d'administration. Exécutez:

 python manage.py loaddata ../fixture.json[196590263/5Exécutiondel'exempledeprojet

Enfin, vous êtes prêt à exécuter l'exemple de code. Pour exécuter le serveur, utilisez la commande suivante:

 python manage.py runserver 

Ouvrez votre navigateur sur http://127.0.0.1:8000 pour afficher le projet. Notez que vous êtes automatiquement redirigé vers le panneau d'administration à / admin / . J'ai accompli cela avec la configuration suivante dans library / urls.py :

 depuis django.contrib import admin
depuis le chemin d'importation de django.urls
des enregistrements importent des vues

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index),
] 

combiné avec la redirection simple suivante dans records / views.py :

 de django.http import HttpResponseRedirect

index de déf (demande):
    return HttpResponseRedirect ('/ admin /') 

Utilisation du panneau d'administration

Nous l'avons fait! Lorsque vous chargez votre page, vous devriez voir quelque chose comme ceci:

Page principale du panneau d'administration Django. ( Grand aperçu )

Cette vue est réalisée avec le code passe-partout suivant dans records / admin.py :

 depuis django.contrib import admin
depuis .models import Book, Patron, Copy

admin.site.register (Livre)
admin.site.register (Copier)
admin.site.register (Patron) 

Cette vue devrait vous donner une première compréhension des données que le système stocke. Je vais supprimer une partie du mystère: Les groupes et Les utilisateurs sont définis par Django et stockent les informations et les autorisations pour les comptes sur le système. Vous pouvez en savoir plus sur le modèle User dans un article antérieur de cette série . Livres Copys et Patrons sont des tableaux de la base de données que nous avons créés lors de l'exécution des migrations et remplis en chargeant le luminaire. Notez que Django pluralise naïvement les noms de modèle en ajoutant un «s», même dans des cas comme «copys» où l'orthographe est incorrecte.

Data Model. ( Grand aperçu )

Dans notre projet, un Livre est un enregistrement avec un titre, un auteur, une date de publication et un ISBN (International Standard Book Number). La bibliothèque conserve une copie de chaque livre ou peut-être plusieurs. Chaque Copie peut être récupérée par un Patron ou pourrait actuellement être archivée. Un Patron est une extension du Utilisateur qui enregistre leur adresse et leur date de naissance.

Créer, lire, mettre à jour, détruire

L'une des fonctionnalités standard du panneau d'administration consiste à ajouter des instances de chaque modèle. Cliquez sur "livres" pour accéder à la page du modèle, puis cliquez sur le bouton "Ajouter un livre" dans le coin supérieur droit. Cela affichera un formulaire que vous pourrez remplir et enregistrer pour créer un livre.

Créer un livre ( Grand aperçu )

Créer un Patron révèle un autre capacité intégrée du formulaire de création de l'administrateur: vous pouvez créer le modèle connecté directement à partir du même formulaire. La capture d'écran ci-dessous montre la fenêtre contextuelle déclenchée par le signe plus vert à droite de la liste déroulante Utilisateur . Ainsi, vous pouvez créer les deux modèles sur la même page d'administration.

Create a Patron. ( Grand aperçu )

Vous pouvez créer une COPIE via le même mécanisme.

Pour chaque enregistrement, vous pouvez cliquer sur la ligne pour la modifier à l'aide du même formulaire. Vous pouvez également supprimer des enregistrements à l'aide d'une action d'administration.

Actions d'administration

Bien que les fonctionnalités intégrées du panneau d'administration soient largement utiles, vous pouvez créer vos propres outils à l'aide des actions d'administration. Nous allons en créer deux: un pour créer des copies de livres et un pour archiver les livres qui ont été retournés à la bibliothèque.

Pour créer une copie d'un livre allez à l'URL / admin / records / book / et utilisez le menu déroulant "Action" pour sélectionner "Ajouter une copie de livre (s)" puis utilisez les cases à cocher dans la colonne de gauche du tableau pour sélectionner le ou les livres dont vous souhaitez ajouter une copie à l'inventaire.

Créer une action de copie. ( Grand aperçu )

La création de cette méthode repose sur une méthode de modèle que nous aborderons plus tard. Nous pouvons l'appeler en tant qu'action d'administration en créant une classe ModelAdmin pour le modèle Profile comme suit dans records / admin.py :

 à partir de django. admin import contrib
depuis .models import Book, Patron, Copy

classe BookAdmin (admin.ModelAdmin):
    list_display = ("titre", "auteur", "publié")
    actions = ["make_copys"]

    def make_copys (self, request, queryset):
        pour q dans le jeu de requêtes:
            q.make_copy ()
        self.message_user (requête, "copie (s) créée (s)")
    make_copys.short_description = "Ajouter une copie de livre (s)"

admin.site.register (Book, BookAdmin) 

La propriété list_display indique les champs utilisés pour représenter le modèle dans la page de présentation du modèle. La propriété actions répertorie les actions d'administration. Notre action d'administration est définie comme une fonction dans BookAdmin et prend trois arguments: l'objet admin lui-même, la requête (la requête HTTP réelle envoyée par le client) et le jeu de requêtes (la liste des objets dont les cases ont été vérifié). Nous effectuons la même action sur chaque élément du jeu de requêtes, puis informons l'utilisateur que les actions ont été effectuées. Chaque action d'administration nécessite une brève description afin de pouvoir être correctement identifiée dans le menu déroulant. Enfin, nous ajoutons maintenant BookAdmin lors de l'enregistrement du modèle.

L'écriture d'actions d'administration pour définir des propriétés en bloc est assez répétitive. Voici le code pour archiver une copie notez sa quasi-équivalence avec l'action précédente.

 de django.contrib import admin
depuis .models import Book, Patron, Copy

classe CopyAdmin (admin.ModelAdmin):
    actions = ["check_in_copys"]

    def check_in_copys (auto, requête, ensemble de requêtes):
        pour q dans le jeu de requêtes:
            q.check_in ()
        self.message_user (demande, "copie (s) archivée")
    check_in_copys.short_description = "Archiver les copies"

admin.site.register (Copy, CopyAdmin) 

Thème Admin

Par défaut, Django fournit des styles assez simples pour le panneau d'administration. Vous pouvez créer votre propre thème ou utiliser un thème tiers pour donner un nouveau look au panneau d'administration. Un thème open-source populaire est grappelli, que nous avons installé plus tôt dans l'article. Vous pouvez consulter la documentation pour ses capacités complètes.

L'installation du thème est assez simple, elle ne nécessite que deux lignes. Tout d'abord, ajoutez grappelli à INSTALLED_APPS comme suit dans library / settings.py :

 INSTALLED_APPS = [
    'grappelli',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'records',
] 

Ensuite, ajustez library / urls.py :

 à partir de django.contrib import admin
à partir du chemin d'importation django.urls, inclure
des enregistrements importent des vues

urlpatterns = [
    path('grappelli/', include('grappelli.urls')),
    path('admin/', admin.site.urls),
    path('', views.index),
] 

Avec ces modifications en place, le panneau d'administration devrait ressembler à ceci:

Panneau d'administration avec thème. ( Grand aperçu )

Il existe un certain nombre d'autres thèmes, et vous pouvez développer votre propre . Je vais m'en tenir à l'aspect par défaut pour le reste de cet article.

Comprendre les modèles

Maintenant que vous êtes à l'aise avec le panneau d'administration et que vous l'utilisez pour parcourir les données, jetons un coup d'œil aux modèles qui définir notre structure de base de données. Chaque modèle représente une table dans une base de données relationnelle.

Une base de données relationnelle stocke les données dans une ou plusieurs tables. Chacune de ces tables a une structure de colonnes spécifiée, y compris une clé primaire (un identifiant unique pour chaque élément) et une ou plusieurs colonnes de valeurs, qui sont de différents types comme des chaînes, des entiers et des dates. Chaque objet stocké dans la base de données est représenté sur une seule ligne. La partie «relationnelle» du nom vient de ce qui est sans doute la caractéristique la plus importante de la technologie: créer des relations entre les tables. Un objet (ligne) peut avoir un mappage un-à-un, un-à-plusieurs (clé étrangère) ou plusieurs-à-plusieurs avec des lignes dans d'autres tables. Nous allons en discuter plus en détail dans les exemples.

Django, par défaut, utilise SQLite3 pour le développement. SQLite3 est un moteur de base de données relationnelle simple et votre base de données est automatiquement créée en tant que db.sqlite3 la première fois que vous exécutez python manage.py migrate . Nous allons continuer avec SQLite3 pour cet article, mais il ne convient pas pour une utilisation en production, principalement parce que les remplacements sont possibles avec des utilisateurs simultanés. En production, ou lors de l'écriture d'un système que vous comptez un jour déployer, utilisez PostgreSQL ou MySQL.

Django utilise des modèles pour s'interfacer avec la base de données. En utilisant une partie de l'ORM de Django, le fichier records / models.py comprend plusieurs modèles, ce qui permet de spécifier des champs, des propriétés et des méthodes pour chaque objet. Lors de la création de modèles, nous nous efforçons d'adopter une architecture «Fat Model», dans des limites raisonnables. Cela signifie que la plus grande partie possible de la validation, de l'analyse, du traitement, de la logique métier, de la gestion des exceptions, de la résolution des cas limites et des tâches similaires doit être traitée dans la spécification du modèle lui-même. Sous le capot, les modèles Django sont des objets très complexes et fonctionnels avec un comportement par défaut largement utile. Cela rend l'architecture «Fat Model» facile à réaliser même sans écrire une quantité substantielle de code.

Passons en revue les trois modèles de notre exemple d'application. Nous ne pouvons pas tout couvrir, car il est censé être un article d'introduction, pas la documentation complète du framework Django, mais je vais souligner les choix les plus importants que j'ai faits dans la construction de ces modèles simples.

The Book classe est le plus simple des modèles. Le voici à partir de records / models.py :

 à partir de django.db import models

Livre de classe (models.Model):
    title = models.CharField (max_length = 300)
    author = models.CharField (max_length = 150)
    published = models.DateField ()
    isbn = models.IntegerField (unique = True)

    def __str __ (auto):
        return self.title + "by" + self.author

    def make_copy (auto):
        Copy.objects.create (book = self) 

Tous les champs CharField nécessitent un attribut max_length spécifié. La longueur conventionnelle est de 150 caractères, que j'ai doublée pour le titre en cas de titres très longs. Bien sûr, il existe toujours une limite arbitraire, qui pourrait être dépassée. Pour une longueur de texte illimitée, utilisez un TextField . Le champ publié est un DateField . L'heure de publication du livre n'a pas d'importance, mais si c'était le cas, j'utiliserais un DateTimeField . Enfin, l'ISBN est un entier (les ISBN sont à 10 ou 13 chiffres et correspondent donc tous à la valeur maximale de l'entier) et nous utilisons unique = True car deux livres ne peuvent pas avoir le même ISBN, qui est ensuite appliqué.

Tous les objets ont une méthode __ str __ (auto) qui définit leur représentation sous forme de chaîne. Nous remplaçons l'implémentation par défaut fournie par la classe models.Model et représentons plutôt les livres comme «titre par auteur» à tous les endroits où le modèle serait représenté sous forme de chaîne. Rappelons que nous utilisions auparavant list_display dans l'objet admin de Livre pour déterminer les champs qui seraient affichés dans la liste du panneau d'administration. Si cette list_display n'est pas présente, la liste admin affiche à la place la représentation sous forme de chaîne du modèle, comme elle le fait pour Patron et Copy .

Enfin , nous avons une méthode sur Book que nous avons appelée dans son action d'administration que nous avons écrite plus tôt. Cette fonction crée une copie qui est liée à une instance donnée d'un livre dans la base de données.

Passant à Patron ce modèle présente le concept d'une relation un-à-un, dans ce cas avec le modèle User intégré. Découvrez-le dans records / models.py :

 dans django.db import models
depuis django.contrib.auth.models import User

Patron de classe (modèles.Modèle):
    user = models.OneToOneField (Utilisateur, on_delete = models.CASCADE)
    address = models.CharField (max_length = 150)
    dob = models.DateField ()

    def __str __ (auto):
        return self.user.username 

Le champ user n'est pas exactement une fonction bijective. Il peut y avoir une instance Utilisateur sans une instance Patron associée. Cependant, un utilisateur NE PEUT PAS être associé à plusieurs instances de Patron et un Patron ne peut pas exister sans une seule relation avec un utilisateur. Ceci est appliqué au niveau de la base de données et est garanti par la spécification on_delete = models.CASCADE : si une instance User est supprimée, un profil associé sera supprimé

Les autres champs et la fonction __ str __ (self) que nous avons vus auparavant. Il convient de noter que vous pouvez accéder via une relation un-à-un pour obtenir des attributs, dans ce cas user.username dans les fonctions d'un modèle.

Pour développer l'utilité des relations de base de données, nous allons tournons notre attention vers Copier de records / models.py :

 à partir de django.db import models

Copie de classe (models.Model):
    book = models.ForeignKey (Book, on_delete = models.CASCADE)
    out_to = models.ForeignKey (Patron, blank = True, null = True, on_delete = models.SET_NULL)

    def __str __ (auto):
        has_copy = "enregistré"
        si self.out_to:
            has_copy = self.out_to.user.username
        return self.book.title + "->" + has_copy
    
    def check_out (self, p):
        self.out_to = p
        self.save ()
    
    def check_in (auto):
        self.out_to = Aucun
        self.save ()

Encore une fois, nous en avons déjà vu la plupart, alors concentrons-nous sur les nouveautés: models.ForeignKey . Une copie doit être d'un seul livre mais la bibliothèque peut avoir plusieurs copie de chaque livre . Un livre peut exister dans la base de données sans que la bibliothèque ait une copie dans son catalogue, mais une copie ne peut exister sans un sous-jacent livre .

Cette relation complexe s'exprime par la ligne suivante:

 book = models.ForeignKey (Book, on_delete = models.CASCADE) 

Le comportement de suppression est le même que celui de Patron . en référence à Utilisateur .

La relation entre une copie et un Patron est légèrement différente. Une copie peut être extraite jusqu'à un mécène mais chaque mécène peut extraire autant de copie que la bibliothèque les laisse. Cependant, il ne s'agit pas d'une relation permanente, la copie n'est parfois pas récupérée. Les mécènes et les copies existent indépendamment les uns des autres dans la base de données; la suppression d'une instance de l'un ne doit supprimer aucune instance de l'autre.

Cette relation est toujours un cas d'utilisation pour la clé étrangère, mais avec des arguments différents:

 out_to = models.ForeignKey (Patron, blank = True, null = True, on_delete = models.SET_NULL)

Ici, avoir blank = True permet aux formulaires d'accepter Aucun comme valeur pour la relation et null = True permet la colonne pour le Relation patron dans la table de Copier dans la base de données accepte null comme valeur. Le comportement de suppression, qui serait déclenché sur une Copie si une instance de Patron était supprimée alors qu'ils avaient cette Copie extraite, est de rompre la relation en quittant Copiez intact en définissant le champ Patron sur null.

Le même type de champ, models.ForeignKey peut exprimer des relations très différentes entre les objets. La seule relation que je ne pouvais pas tenir correctement dans l'exemple est un champ plusieurs-à-plusieurs, qui est comme un champ un-à-un, sauf que, comme son nom l'indique, chaque instance peut être liée à de nombreuses autres instances et tous les autres et chacun de ceux-ci peuvent être liés à de nombreux autres, comme la façon dont un livre peut avoir plusieurs auteurs, chacun ayant écrit plusieurs livres.

Migrations

Vous vous demandez peut-être comment la base de données sait ce qui est exprimé dans le modèle. D'après mon expérience, les migrations sont l'une de ces choses qui sont assez simples jusqu'à ce qu'elles ne le soient pas, puis elles mangent votre visage. Voici comment garder votre tasse intacte, pour les débutants: découvrez les migrations et comment interagir avec elles, mais essayez d'éviter de modifier manuellement les fichiers de migration. Si vous savez déjà ce que vous faites, sautez cette section et continuez ce qui fonctionne pour vous.

Quoi qu'il en soit, consultez la documentation officielle pour un traitement complet du sujet.

Migrations traduire les modifications d'un modèle en modifications du schéma de la base de données. Vous n'avez pas à les écrire vous-même, Django les crée avec la commande python manage.py makemigrations . Vous devez exécuter cette commande lorsque vous créez un nouveau modèle ou modifiez les champs d'un modèle existant, mais cela n'est pas nécessaire lors de la création ou de la modification des méthodes de modèle. Il est important de noter que les migrations existent en tant que chaîne, chacune fait référence à la précédente afin de pouvoir apporter des modifications sans erreur au schéma de la base de données. Ainsi, si vous collaborez sur un projet, il est important de conserver un seul historique de migration cohérent dans le contrôle de version. Lorsqu'il y a des migrations non appliquées, exécutez python manage.py migrate pour les appliquer avant d'exécuter le serveur.

L'exemple de projet est distribué avec une seule migration, records / migrations / 0001_initial.py . Encore une fois, c'est du code généré automatiquement que vous ne devriez pas avoir à modifier, donc je ne le copierai pas ici, mais si vous voulez avoir une idée de ce qui se passe dans les coulisses, allez-y et jetez-y un œil.

Fixtures

Contrairement aux migrations, les fixtures ne sont pas un aspect courant du développement de Django. Je les utilise pour distribuer des exemples de données avec des articles, et je ne les ai jamais utilisés autrement. Cependant, parce que nous en avons utilisé un plus tôt, je me sens obligé de présenter le sujet.

Pour une fois, la documentation officielle est un peu mince sur le sujet. Dans l'ensemble, ce que vous devez savoir, c'est que les appareils sont un moyen d'importer et d'exporter des données de votre base de données dans une variété de formats, y compris JSON, ce que j'utilise. Cette fonctionnalité existe principalement pour aider avec des choses comme les tests automatisés, et n'est pas un système de sauvegarde ou un moyen de modifier des données dans une base de données en direct. De plus, les appareils ne sont pas mis à jour avec les migrations et si vous essayez d'appliquer un appareil à une base de données avec un schéma incompatible, il échouera.

Pour générer un appareil pour la base de données entière, exécutez:

 python manage.py dumpdata --format json> fixture.json

Pour charger un appareil, exécutez:

 python manage.py loaddata fixture.json

Conclusion

L'écriture de modèles dans Django est un sujet énorme, et l'utilisation du panneau d'administration en est un autre. En 3 000 mots, je n'ai réussi qu'à les présenter chacun. Avec un peu de chance, l'utilisation du panneau d'administration vous a donné une meilleure interface pour explorer comment les modèles fonctionnent et interagissent les uns avec les autres, vous laissant avec la confiance nécessaire pour expérimenter et développer vos propres représentations relationnelles des données. Pour commencer, essayez d'ajouter un modèle Bibliothécaire qui hérite de l'utilisateur comme le fait le profil . Pour plus de difficulté, essayez d'implémenter un historique de paiement pour chaque Copie et / ou Patron (il existe plusieurs façons d'y parvenir).

Django Highlights est une série présentant concepts importants du développement web dans Django. Chaque article est écrit comme un guide autonome sur une facette du développement de Django destiné à aider les développeurs et les concepteurs frontaux à approfondir leur compréhension de «l'autre moitié» de la base de code. Ces articles sont principalement construits pour vous aider à comprendre la théorie et les conventions, mais contiennent des exemples de code qui sont écrits dans Django 3.0.

Lectures complémentaires

Les articles et la documentation suivants peuvent vous intéresser.

(dm, yk, il)




Source link
Quitter la version mobile