{"title":"Écriture de votre première application Django, 2ème partie","version":"3.2","locale":"fr","docname":"intro/tutorial02","url":"/fr/3.2/intro/tutorial02/","canonical":"https://djangodocs.dev/fr/3.2/intro/tutorial02/","summary":"Ce tutoriel commence là où le tutoriel 1 s’achève. Nous allons configurer la base de données, créer le premier modèle et aborder une introduction rapide au site…","html":"<h1>Écriture de votre première application Django, 2ème partie<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-2\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Ce tutoriel commence là où le <a class=\"reference internal\" href=\"/fr/3.2/intro/tutorial01/\"><span class=\"doc\">tutoriel 1</span></a> s’achève. Nous allons configurer la base de données, créer le premier modèle et aborder une introduction rapide au site d’administration généré automatiquement par Django.</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">Où obtenir de l’aide :</p>\n<p>Si vous rencontrez des problèmes dans le parcours de ce tutoriel, rendez-vous dans la section <a class=\"reference internal\" href=\"/fr/3.2/faq/help/\"><span class=\"doc\">Obtenir de l’aide</span></a> de la FAQ.</p>\n</aside>\n<section id=\"database-setup\">\n<h2>Configuration de la base de données<a class=\"heading-anchor\" href=\"#database-setup\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Maintenant, ouvrez <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code>. C’est un module Python tout à fait normal, avec des variables de module qui représentent des réglages de Django.</p>\n<p>La configuration par défaut utilise SQLite. Si vous débutez avec les bases de données ou que vous voulez juste essayer Django, il s’agit du choix le plus simple. SQLite est inclus dans Python, vous n’aurez donc rien d’autre à installer pour utiliser ce type de base de données. Lorsque vous démarrez votre premier projet réel, cependant, vous pouvez utiliser une base de données plus résistante à la charge comme PostgreSQL, afin d’éviter les maux de tête consécutifs au changement perpétuel d’une base de données à l’autre.</p>\n<p>Si vous souhaitez utiliser une autre base de données, installez le <a class=\"reference internal\" href=\"/fr/3.2/topics/install/#database-installation\"><span class=\"std std-ref\">connecteur de base de données</span></a> approprié, et changez les clés suivantes dans l’élément <code class=\"docutils literal notranslate\"><span class=\"pre\">'default'</span></code> de <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> pour indiquer les paramètres de connexion de votre base de données :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-DATABASE-ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ENGINE</span></code></a> – Choisissez parmi <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.sqlite3'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.postgresql'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.mysql'</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.oracle'</span></code>. D’autres moteurs sont <a class=\"reference internal\" href=\"/fr/3.2/ref/databases/#third-party-notes\"><span class=\"std std-ref\">également disponibles</span></a>.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a> – Le nom de votre base de données. Si vous utilisez SQLite, la base de données sera un fichier sur votre ordinateur. Dans ce cas, <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a> doit être le chemin absolu complet de celui-ci, y compris le nom de fichier. La valeur par défaut, <code class=\"docutils literal notranslate\"><span class=\"pre\">BASE_DIR</span> <span class=\"pre\">/</span> <span class=\"pre\">'db.sqlite3'</span></code>, stocke ce fichier dans le répertoire de votre projet.</p></li>\n</ul>\n<p>Si vous utilisez une autre base de données que SQLite, des réglages supplémentaires doivent être indiqués, comme <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-USER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USER</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-PASSWORD\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD</span></code></a> ou <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a>. Pour plus de détails, consultez la documentation de référence de <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a>.</p>\n<aside class=\"admonition-for-databases-other-than-sqlite admonition\">\n<p class=\"admonition-title\">Pour les bases de données autres que SQLite</p>\n<p>Si vous utilisez une base de données autre que SQLite, assurez-vous maintenant d’avoir créé la base de données. Faites-le avec <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">DATABASE</span> <span class=\"pre\">nom_de_la_base;</span></code> dans le shell interactif de votre base de données.</p>\n<p>Vérifiez également que l’utilisateur de base de données indiqué dans le fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> possède la permission de créer des bases de données. Cela permet de créer automatiquement une <a class=\"reference internal\" href=\"/fr/3.2/topics/testing/overview/#the-test-database\"><span class=\"std std-ref\">base de données de test</span></a> qui sera nécessaire plus tard dans le tutoriel.</p>\n<p>Si vous utilisez SQLite, vous n’avez rien à créer à l’avance - le fichier de la base de données sera automatiquement créé lorsque ce sera nécessaire.</p>\n</aside>\n<p>Puisque vous êtes en train d’éditer <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code>, définissez <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a> selon votre fuseau horaire.</p>\n<p>Notez également le réglage <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> au début du fichier. Cette variable contient le nom des applications Django qui sont actives dans cette instance de Django. Les applications peuvent être utilisées dans des projets différents, et vous pouvez empaqueter et distribuer les vôtres pour que d’autres les utilisent dans leurs projets.</p>\n<p>Par défaut, <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> contient les applications suivantes, qui sont toutes contenues dans Django :</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/admin/#module-django.contrib.admin\" title=\"django.contrib.admin: Django's admin site.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.admin</span></code></a> – Le site d’administration. Vous l’utiliserez très bientôt.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code></a> – Un système d’authentification.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/contenttypes/#module-django.contrib.contenttypes\" title=\"django.contrib.contenttypes: Provides generic interface to installed models.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.contenttypes</span></code></a> – Une structure pour les types de contenu (content types).</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/topics/http/sessions/#module-django.contrib.sessions\" title=\"django.contrib.sessions: Provides session management for Django projects.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions</span></code></a> – Un cadre pour les sessions.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/messages/#module-django.contrib.messages\" title=\"django.contrib.messages: Provides cookie- and session-based temporary message storage.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.messages</span></code></a> – Un cadre pour l’envoi de messages.</p></li>\n<li><p><a class=\"reference internal\" href=\"/fr/3.2/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.staticfiles</span></code></a> – Une structure pour la prise en charge des fichiers statiques.</p></li>\n</ul>\n<p>Ces applications sont incluses par défaut par commodité parce que ce sont les plus communément utilisées.</p>\n<p>Certaines de ces applications utilisent toutefois au moins une table de la base de données, donc il nous faut créer les tables dans la base avant de pouvoir les utiliser. Pour ce faire, lancez la commande suivante :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>migrate\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py migrate\n</code></pre></div></div></div>\n<p>La commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> examine le réglage <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> et crée les tables de base de données nécessaires en fonction des réglages de base de données dans votre fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> et des migrations de base de données contenues dans l’application (nous les aborderons plus tard). Vous verrez apparaître un message pour chaque migration appliquée. Si cela vous intéresse, lancez le client en ligne de commande de votre base de données et tapez <code class=\"docutils literal notranslate\"><span class=\"pre\">\\dt</span></code> (PostgreSQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">SHOW</span> <span class=\"pre\">TABLES;</span></code> (MariaDB, MySQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">.schema</span></code> (SQLite) ou <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">TABLE_NAME</span> <span class=\"pre\">FROM</span> <span class=\"pre\">USER_TABLES;</span></code> (Oracle) pour afficher les tables créées par Django.</p>\n<aside class=\"admonition-for-the-minimalists admonition\">\n<p class=\"admonition-title\">Pour les minimalistes</p>\n<p>Comme il a été indiqué ci-dessus, les applications incluses par défaut sont les plus communes, mais tout le monde n’en a pas forcément besoin. Si vous n’avez pas besoin d’une d’entre elles (ou de toutes), vous êtes libre de commenter ou effacer les lignes concernées du règlage <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> avant de lancer <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a>. La commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> n’exécutera les migrations que pour les applications listées dans <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>.</p>\n</aside>\n</section>\n<section id=\"creating-models\">\n<span id=\"id1\"></span><h2>Création des modèles<a class=\"heading-anchor\" href=\"#creating-models\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Nous allons maintenant définir les modèles – essentiellement, le schéma de base de données, avec quelques métadonnées supplémentaires.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">Philosophie</p>\n<p>Un modèle est la source d’information unique et définitive pour vos données. Il contient les champs essentiels et le comportement attendu des données que vous stockerez. Django respecte la <a class=\"reference internal\" href=\"/fr/3.2/misc/design-philosophies/#dry\"><span class=\"std std-ref\">philosophie DRY</span></a> (Don’t Repeat Yourself, « ne vous répétez pas »). Le but est de définir le modèle des données à un seul endroit, et ensuite de dériver automatiquement ce qui est nécessaire à partir de celui-ci.</p>\n<p>Ceci inclut les migrations. Au contraire de Ruby On Rails, par exemple, les migrations sont entièrement dérivées du fichier des modèles et ne sont au fond qu’un historique que Django peut parcourir pour mettre à jour le schéma de la base de données pour qu’il corresponde aux modèles actuels.</p>\n</aside>\n<p>Dans notre application de sondage, nous allons créer deux modèles : <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> (choix). Une <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> possède une question et une date de mise en ligne. Un choix a deux champs : le texte représentant le choix et le décompte des votes. Chaque choix est associé à une <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>.</p>\n<p>Ces concepts sont représentés par des classes Python. Éditez le fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code> de façon à ce qu’il ressemble à ceci :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">question_text</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    <span class=\"n\">pub_date</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">DateTimeField</span><span class=\"p\">(</span><span class=\"s1\">&#39;date published&#39;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Choice</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">)</span>\n    <span class=\"n\">choice_text</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    <span class=\"n\">votes</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Ici, chaque modèle est représenté par une classe qui hérite de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/instances/#django.db.models.Model\" title=\"django.db.models.Model\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.db.models.Model</span></code></a>. Chaque modèle possède des variables de classe, chacune d’entre elles représentant un champ de la base de données pour ce modèle.</p>\n<p>Chaque champ est représenté par une instance d’une classe <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> – par exemple, <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> pour les champs de type caractère, et <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> pour les champs date et heure. Cela indique à Django le type de données que contient chaque champ.</p>\n<p>Le nom de chaque instance de <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> (par exemple, <code class=\"docutils literal notranslate\"><span class=\"pre\">question_text</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code>) est le nom du champ en interne. Vous l’utiliserez dans votre code Python et votre base de données l’utilisera comme nom de colonne.</p>\n<p>Vous pouvez utiliser le premier paramètre de position (facultatif) d’un <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> pour donner un nom plus lisible au champ. C’est utilisé par le système d’introspection de Django, et aussi pour la documentation. Si ce paramètre est absent, Django utilisera le nom du champ interne. Dans l’exemple, nous n’avons défini qu’un seul nom plus lisible, pour <code class=\"docutils literal notranslate\"><span class=\"pre\">Question.pub_date</span></code>. Pour tous les autres champs, nous avons considéré que le nom interne était suffisamment lisible.</p>\n<p>Certaines classes <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> possèdent des paramètres obligatoires. La classe <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a>, par exemple, a besoin d’un attribut <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.CharField.max_length\" title=\"django.db.models.CharField.max_length\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">max_length</span></code></a>. Ce n’est pas seulement utilisé dans le schéma de base de la base de données, mais également pour valider les champs, comme nous allons voir prochainement.</p>\n<p>Un champ <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> peut aussi autoriser des paramètres facultatifs ; dans notre cas, nous avons défini à 0 la valeur <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">default</span></code></a> de <code class=\"docutils literal notranslate\"><span class=\"pre\">votes</span></code>.</p>\n<p>Finalement, notez que nous définissons une relation, en utilisant <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code></a>. Cela indique à Django que chaque vote (<code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>) n’est relié qu’à une seule <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>. Django propose tous les modèles classiques de relations : plusieurs-à-un, plusieurs-à-plusieurs, un-à-un.</p>\n</section>\n<section id=\"activating-models\">\n<h2>Activation des modèles<a class=\"heading-anchor\" href=\"#activating-models\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ce petit morceau de code décrivant les modèles fournit beaucoup d’informations à Django. Cela lui permet de :</p>\n<ul class=\"simple\">\n<li><p>Créer un schéma de base de données (instructions <code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code>) pour cette application.</p></li>\n<li><p>Créer une API Python d’accès aux bases de données pour accéder aux objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>.</p></li>\n</ul>\n<p>Mais il faut d’abord indiquer à notre projet que l’application de sondages <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> est installée.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">Philosophie</p>\n<p>Les applications de Django sont comme des pièces d’un jeu de construction : vous pouvez utiliser une application dans plusieurs projets, et vous pouvez distribuer les applications, parce qu’elles n’ont pas besoin d’être liées à une installation Django particulière.</p>\n</aside>\n<p>Pour inclure l’application dans notre projet, nous avons besoin d’ajouter une référence à sa classe de configuration dans le réglage <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>. La classe <code class=\"docutils literal notranslate\"><span class=\"pre\">PollsConfig</span></code> se trouve dans le fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/apps.py</span></code>, ce qui signifie que son chemin pointé est <code class=\"docutils literal notranslate\"><span class=\"pre\">'polls.apps.PollsConfig'</span></code>. Modifiez le fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> et ajoutez ce chemin pointé au réglage <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>. Il doit ressembler à ceci :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">INSTALLED_APPS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;polls.apps.PollsConfig&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.admin&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.contenttypes&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.sessions&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.messages&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.staticfiles&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Maintenant, Django sait qu’il doit inclure l’application <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>. Exécutons une autre commande :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-1-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>makemigrations<span class=\"w\"> </span>polls\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-1-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py makemigrations polls\n</code></pre></div></div></div>\n<p>Vous devriez voir quelque chose de similaire à ceci :</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Migrations for &#39;polls&#39;:\n  polls/migrations/0001_initial.py\n    - Create model Question\n    - Create model Choice\n</code></pre></div>\n<p>En exécutant <code class=\"docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code>, vous indiquez à Django que vous avez effectué des changements à vos modèles (dans ce cas, vous en avez créé) et que vous aimeriez que ces changements soient stockés sous forme de <em>migration</em>.</p>\n<p>Les migrations sont le moyen utilisé par Django pour stocker les modifications de vos modèles (et donc de votre schéma de base de données), il s’agit de fichiers sur un disque. Vous pouvez consultez la migration pour vos nouveaux modèles si vous le voulez ; il s’agit du fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/migrations/0001_initial.py</span></code>. Soyez sans crainte, vous n’êtes pas censé les lire chaque fois que Django en crée, mais ils sont conçus pour être humainement lisibles au cas où vous auriez besoin d’adapter manuellement les processus de modification de Django.</p>\n<p>Il existe une commande qui exécute les migrations et gère automatiquement votre schéma de base de données, elle s’appelle <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a>. Nous y viendrons bientôt, mais tout d’abord, voyons les instructions SQL que la migration produit. La commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-sqlmigrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlmigrate</span></code></a> accepte des noms de migrations et affiche le code SQL correspondant :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-2-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>sqlmigrate<span class=\"w\"> </span>polls<span class=\"w\"> </span><span class=\"m\">0001</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-2-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py sqlmigrate polls 0001\n</code></pre></div></div></div>\n<p>Vous devriez voir quelque chose de similaire à ceci (remis en forme par souci de lisibilité) :</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">BEGIN</span><span class=\"p\">;</span>\n<span class=\"c1\">--</span>\n<span class=\"c1\">-- Create model Question</span>\n<span class=\"c1\">--</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_question&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;id&quot;</span><span class=\"w\"> </span><span class=\"nb\">serial</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"w\"> </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;question_text&quot;</span><span class=\"w\"> </span><span class=\"nb\">varchar</span><span class=\"p\">(</span><span class=\"mi\">200</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;pub_date&quot;</span><span class=\"w\"> </span><span class=\"k\">timestamp</span><span class=\"w\"> </span><span class=\"k\">with</span><span class=\"w\"> </span><span class=\"k\">time</span><span class=\"w\"> </span><span class=\"k\">zone</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n<span class=\"c1\">--</span>\n<span class=\"c1\">-- Create model Choice</span>\n<span class=\"c1\">--</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;id&quot;</span><span class=\"w\"> </span><span class=\"nb\">serial</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"w\"> </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;choice_text&quot;</span><span class=\"w\"> </span><span class=\"nb\">varchar</span><span class=\"p\">(</span><span class=\"mi\">200</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;votes&quot;</span><span class=\"w\"> </span><span class=\"nb\">integer</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"w\"> </span><span class=\"nb\">integer</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span>\n<span class=\"w\">  </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">CONSTRAINT</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice_question_id_c5b4b260_fk_polls_question_id&quot;</span>\n<span class=\"w\">    </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_question&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;id&quot;</span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">DEFERRABLE</span><span class=\"w\"> </span><span class=\"k\">INITIALLY</span><span class=\"w\"> </span><span class=\"k\">DEFERRED</span><span class=\"p\">;</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">INDEX</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice_question_id_c5b4b260&quot;</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"p\">);</span>\n\n<span class=\"k\">COMMIT</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>Notez les points suivants :</p>\n<ul class=\"simple\">\n<li><p>Ce que vous verrez dépendra de la base de données que vous utilisez. L’exemple ci-dessus est généré pour PostgreSQL.</p></li>\n<li><p>Les noms de tables sont générés automatiquement en combinant le nom de l’application (<code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>) et le nom du modèle en minuscules – <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">choice</span></code> (vous pouvez modifier ce comportement).</p></li>\n<li><p>Des clés primaires (ID) sont ajoutées automatiquement (vous pouvez modifier ceci également).</p></li>\n<li><p>Par convention, Django ajoute <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;_id&quot;</span></code> au nom de champ de la clé étrangère. Et oui, vous pouvez aussi changer ça.</p></li>\n<li><p>La relation de clé étrangère est rendue explicite par une contrainte <code class=\"docutils literal notranslate\"><span class=\"pre\">FOREIGN</span> <span class=\"pre\">KEY</span></code>. Ne prenez pas garde aux parties <code class=\"docutils literal notranslate\"><span class=\"pre\">DEFERRABLE</span></code>; elles indiquent à PostgreSQL de ne pas contrôler la clé étrangère avant la fin de la transaction.</p></li>\n<li><p>Ce que vous voyez est adapté à la base de données que vous utilisez. Ainsi, des champs spécifiques à celle-ci comme <code class=\"docutils literal notranslate\"><span class=\"pre\">auto_increment</span></code> (MySQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">serial</span></code> (PostgreSQL) ou <code class=\"docutils literal notranslate\"><span class=\"pre\">integer</span> <span class=\"pre\">primary</span> <span class=\"pre\">key</span> <span class=\"pre\">autoincrement</span></code> (SQLite) sont gérés pour vous automatiquement. Tout comme pour les guillemets autour des noms de champs (simples ou doubles).</p></li>\n<li><p>La commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-sqlmigrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlmigrate</span></code></a> n’exécute pas réellement la migration dans votre base de données - elle se contente de l’afficher à l’écran de façon à vous permettre de voir le code SQL que Django pense nécessaire. C’est utile pour savoir ce que Django s’apprête à faire ou si vous avez des administrateurs de base de données qui exigent des scripts SQL pour faire les modifications.</p></li>\n</ul>\n<p>Si cela vous intéresse, vous pouvez aussi exécuter <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-check\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">check</span></code></a>; cette commande vérifie la conformité de votre projet sans appliquer de migration et sans toucher à la base de données.</p>\n<p>Maintenant, exécutez à nouveau la commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> pour créer les tables des modèles dans votre base de données :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-3-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>migrate\n<span class=\"go\">Operations to perform:</span>\n<span class=\"go\">  Apply all migrations: admin, auth, contenttypes, polls, sessions</span>\n<span class=\"go\">Running migrations:</span>\n<span class=\"go\">  Rendering model states... DONE</span>\n<span class=\"go\">  Applying polls.0001_initial... OK</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-3-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py migrate\n<span class=\"go\">Operations to perform:</span>\n<span class=\"go\">  Apply all migrations: admin, auth, contenttypes, polls, sessions</span>\n<span class=\"go\">Running migrations:</span>\n<span class=\"go\">  Rendering model states... DONE</span>\n<span class=\"go\">  Applying polls.0001_initial... OK</span>\n</code></pre></div></div></div>\n<p>La commande <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> sélectionne toutes les migrations qui n’ont pas été appliquées (Django garde la trace des migrations appliquées en utilisant une table spéciale dans la base de données : <code class=\"docutils literal notranslate\"><span class=\"pre\">django_migrations</span></code>) puis les exécute dans la base de données, ce qui consiste essentiellement à synchroniser les changements des modèles avec le schéma de la base de données.</p>\n<p>Les migrations sont très puissantes et permettent de gérer les changements de modèles dans le temps, au cours du développement d’un projet, sans devoir supprimer la base de données ou ses tables et en refaire de nouvelles. Une migration s’attache à mettre à jour la base de données en live, sans perte de données. Nous les aborderons plus en détails dans une partie ultérieure de ce didacticiel, mais pour l’instant, retenez le guide en trois étapes pour effectuer des modifications aux modèles :</p>\n<ul class=\"simple\">\n<li><p>Modifiez les modèles (dans <code class=\"docutils literal notranslate\"><span class=\"pre\">models.py</span></code>).</p></li>\n<li><p>Exécutez <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">makemigrations</span></code></a> pour créer des migrations correspondant à ces changements.</p></li>\n<li><p>Exécutez <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code></a> pour appliquer ces modifications à la base de données.</p></li>\n</ul>\n<p>La raison de séparer les commandes pour créer et appliquer les migrations est que celles-ci vont être ajoutées dans votre système de gestion de versions et qu’elles seront livrées avec l’application ; elles ne font pas que faciliter le développement, elles sont également exploitables par d’autres développeurs ou en production.</p>\n<p>Lisez la <a class=\"reference internal\" href=\"/fr/3.2/ref/django-admin/\"><span class=\"doc\">documentation de django-admin</span></a> pour avoir toutes les informations sur ce que <code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span></code> peut faire.</p>\n</section>\n<section id=\"playing-with-the-api\">\n<h2>Jouer avec l’interface de programmation (API)<a class=\"heading-anchor\" href=\"#playing-with-the-api\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Maintenant, utilisons un shell interactif Python pour jouer avec l’API que Django met gratuitement à votre disposition. Pour lancer un shell Python, utilisez cette commande :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-4-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>shell\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-4-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py shell\n</code></pre></div></div></div>\n<p>Nous utilisons celle-ci au lieu de simplement taper « python », parce que <code class=\"file docutils literal notranslate\"><span class=\"pre\">manage.py</span></code> définit la variable d’environnement <span class=\"target\" id=\"index-2\"></span><a class=\"reference internal\" href=\"/fr/3.2/topics/settings/#envvar-DJANGO_SETTINGS_MODULE\"><code class=\"xref std std-envvar docutils literal notranslate\"><span class=\"pre\">DJANGO_SETTINGS_MODULE</span></code></a>, qui indique à Django le chemin d’importation Python vers votre fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code>.</p>\n<p>Une fois dans le shell, explorez l”<a class=\"reference internal\" href=\"/fr/3.2/topics/db/queries/\"><span class=\"doc\">API de base de données</span></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">polls.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>  <span class=\"c1\"># Import the model classes we just wrote.</span>\n\n<span class=\"go\"># No questions are in the system yet.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n\n<span class=\"go\"># Create a new Question.</span>\n<span class=\"go\"># Support for time zones is enabled in the default settings file, so</span>\n<span class=\"go\"># Django expects a datetime with tzinfo for pub_date. Use timezone.now()</span>\n<span class=\"go\"># instead of datetime.datetime.now() and it will do the right thing.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;What&#39;s new?&quot;</span><span class=\"p\">,</span> <span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">())</span>\n\n<span class=\"go\"># Save the object into the database. You have to call save() explicitly.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"go\"># Now it has an ID.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">id</span>\n<span class=\"go\">1</span>\n\n<span class=\"go\"># Access model field values via Python attributes.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span>\n<span class=\"go\">&quot;What&#39;s new?&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">pub_date</span>\n<span class=\"go\">datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=&lt;UTC&gt;)</span>\n\n<span class=\"go\"># Change values by changing the attributes, then calling save().</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;What&#39;s up?&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"go\"># objects.all() displays all the questions in the database.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: Question object (1)&gt;]&gt;</span>\n</code></pre></div>\n<p>Une seconde. <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;Question:</span> <span class=\"pre\">Question</span> <span class=\"pre\">object</span> <span class=\"pre\">(1)&gt;</span></code> n’est pas une représentation très utile de cet objet. On va arranger cela en éditant le modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> (dans le fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code>) et en ajoutant une méthode <a class=\"reference internal\" href=\"/fr/3.2/ref/models/instances/#django.db.models.Model.__str__\" title=\"django.db.models.Model.__str__\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">__str__()</span></code></a> à <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> et à <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">question_text</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Choice</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">choice_text</span>\n</code></pre></figure>\n<p>Il est important d’ajouter des méthodes  <a class=\"reference internal\" href=\"/fr/3.2/ref/models/instances/#django.db.models.Model.__str__\" title=\"django.db.models.Model.__str__\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">__str__()</span></code></a> à vos modèles, non seulement parce que c’est plus pratique lorsque vous utilisez le shell interactif, mais aussi parce que la représentation des objets est très utilisée dans l’interface d’administration automatique de Django.</p>\n<p id=\"tutorial02-import-timezone\">Ajoutons aussi une méthode personnalisée à ce modèle :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">pub_date</span> <span class=\"o\">&gt;=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Notez l’ajout de <code class=\"docutils literal notranslate\"><span class=\"pre\">import</span> <span class=\"pre\">datetime</span></code> et de <code class=\"docutils literal notranslate\"><span class=\"pre\">from</span> <span class=\"pre\">django.utils</span> <span class=\"pre\">import</span> <span class=\"pre\">timezone</span></code>, pour référencer respectivement le module <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#module-datetime\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">datetime</span></code></a> standard de Python et les utilitaires de Django liés aux fuseaux horaires de <a class=\"reference internal\" href=\"/fr/3.2/ref/utils/#module-django.utils.timezone\" title=\"django.utils.timezone: Timezone support.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.utils.timezone</span></code></a>. Si vous n’êtes pas habitué à la gestion des fuseaux horaires avec Python, vous pouvez en apprendre plus en consultant la <a class=\"reference internal\" href=\"/fr/3.2/topics/i18n/timezones/\"><span class=\"doc\">documentation sur les fuseaux horaires</span></a>.</p>\n<p>Enregistrez ces modifications et retournons au shell interactif de Python en exécutant à nouveau <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">shell</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">polls.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n\n<span class=\"go\"># Make sure our __str__() addition worked.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n\n<span class=\"go\"># Django provides a rich database lookup API that&#39;s entirely driven by</span>\n<span class=\"go\"># keyword arguments.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">question_text__startswith</span><span class=\"o\">=</span><span class=\"s1\">&#39;What&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n\n<span class=\"go\"># Get the question that was published this year.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">current_year</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">year</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pub_date__year</span><span class=\"o\">=</span><span class=\"n\">current_year</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># Request an ID that doesn&#39;t exist, this will raise an exception.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"w\">    </span><span class=\"o\">...</span>\n<span class=\"gr\">DoesNotExist</span>: <span class=\"n\">Question matching query does not exist.</span>\n\n<span class=\"x\"># Lookup by a primary key is the most common case, so Django provides a</span>\n<span class=\"x\"># shortcut for primary-key exact lookups.</span>\n<span class=\"x\"># The following is identical to Question.objects.get(id=1).</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># Make sure our custom method worked.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n\n<span class=\"go\"># Give the Question a couple of Choices. The create call constructs a new</span>\n<span class=\"go\"># Choice object, does the INSERT statement, adds the choice to the set</span>\n<span class=\"go\"># of available choices and returns the new Choice object. Django creates</span>\n<span class=\"go\"># a set to hold the &quot;other side&quot; of a ForeignKey relation</span>\n<span class=\"go\"># (e.g. a question&#39;s choice) which can be accessed via the API.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Display any choices from the related object set -- none so far.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n\n<span class=\"go\"># Create three choices.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Not much&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Choice: Not much&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;The sky&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Choice: The sky&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Just hacking again&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Choice objects have API access to their related Question objects.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">question</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># And vice versa: Question objects get access to Choice objects.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Choice: Not much&gt;, &lt;Choice: The sky&gt;, &lt;Choice: Just hacking again&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">count</span><span class=\"p\">()</span>\n<span class=\"go\">3</span>\n\n<span class=\"go\"># The API automatically follows relationships as far as you need.</span>\n<span class=\"go\"># Use double underscores to separate relationships.</span>\n<span class=\"go\"># This works as many levels deep as you want; there&#39;s no limit.</span>\n<span class=\"go\"># Find all Choices for any question whose pub_date is in this year</span>\n<span class=\"go\"># (reusing the &#39;current_year&#39; variable we created above).</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Choice</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">question__pub_date__year</span><span class=\"o\">=</span><span class=\"n\">current_year</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Choice: Not much&gt;, &lt;Choice: The sky&gt;, &lt;Choice: Just hacking again&gt;]&gt;</span>\n\n<span class=\"go\"># Let&#39;s delete one of the choices. Use delete() for that.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">choice_text__startswith</span><span class=\"o\">=</span><span class=\"s1\">&#39;Just hacking&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Pour plus d’informations sur les relations entre modèles, consultez <a class=\"reference internal\" href=\"/fr/3.2/ref/models/relations/\"><span class=\"doc\">Accès aux objets liés</span></a>. Pour en savoir plus sur la manière d’utiliser les doubles soulignements pour explorer les champs par l’API, consultez <a class=\"reference internal\" href=\"/fr/3.2/topics/db/queries/#field-lookups-intro\"><span class=\"std std-ref\">Recherches par champs</span></a>. Pour tous les détails sur l’API de base de données, consultez la <a class=\"reference internal\" href=\"/fr/3.2/topics/db/queries/\"><span class=\"doc\">référence de l’API de base de données</span></a>.</p>\n</section>\n<section id=\"introducing-the-django-admin\">\n<h2>Introduction au site d’administration de Django<a class=\"heading-anchor\" href=\"#introducing-the-django-admin\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">Philosophie</p>\n<p>La génération de sites d’administration pour votre équipe ou vos clients pour ajouter, modifier et supprimer du contenu est un travail pénible qui ne requiert pas beaucoup de créativité. C’est pour cette raison que Django automatise entièrement la création des interfaces d’administration pour les modèles.</p>\n<p>Django a été écrit dans un environnement éditorial, avec une très nette séparation entre les « éditeurs de contenu » et le site « public ». Les gestionnaires du site utilisent le système pour ajouter des nouvelles, des histoires, des événements, des résultats sportifs, etc., et ce contenu est affiché sur le site public. Django résout le problème de création d’une interface uniforme pour les administrateurs du site qui éditent le contenu.</p>\n<p>L’interface d’administration n’est pas destinée à être utilisée par les visiteurs du site ; elle est conçue pour les gestionnaires du site.</p>\n</aside>\n<section id=\"creating-an-admin-user\">\n<h3>Création d’un utilisateur administrateur<a class=\"heading-anchor\" href=\"#creating-an-admin-user\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Nous avons d’abord besoin de créer un utilisateur qui peut se connecter au site d’administration. Lancez la commande suivante :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-5-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>createsuperuser\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-5-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py createsuperuser\n</code></pre></div></div></div>\n<p>Saisissez le nom d’utilisateur souhaité et appuyez sur retour.</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Username: admin\n</code></pre></div>\n<p>On vous demande alors de saisir l’adresse de courriel souhaitée :</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Email address: admin@example.com\n</code></pre></div>\n<p>L’étape finale est de saisir le mot de passe. On vous demande de le saisir deux fois, la seconde fois étant une confirmation de la première.</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Password: **********\nPassword (again): *********\nSuperuser created successfully.\n</code></pre></div>\n</section>\n<section id=\"start-the-development-server\">\n<h3>Démarrage du serveur de développement<a class=\"heading-anchor\" href=\"#start-the-development-server\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le site d’administration de Django est activé par défaut. Lançons le serveur de développement et explorons-le.</p>\n<p>Si le serveur ne tourne pas encore, démarrez-le comme ceci :</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-6-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>runserver\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-6-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py runserver\n</code></pre></div></div></div>\n<p>À présent, ouvrez un navigateur Web et allez à l’URL « /admin/ » de votre domaine local – par exemple, <a class=\"reference external\" href=\"http://127.0.0.1:8000/admin/\">http://127.0.0.1:8000/admin/</a>. Vous devriez voir l’écran de connexion à l’interface d’administration :</p>\n<img alt=\"Django admin login screen\" src=\"/fr/3.2/_images/admin01.png\" />\n<p>Comme la <a class=\"reference internal\" href=\"/fr/3.2/topics/i18n/translation/\"><span class=\"doc\">traduction</span></a> est active par défaut, si vous définissez <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LANGUAGE_CODE</span></code></a>, l’écran de connexion s’affiche dans cette langue (pour autant que les traductions correspondantes existent dans Django).</p>\n</section>\n<section id=\"enter-the-admin-site\">\n<h3>Entrée dans le site d’administration<a class=\"heading-anchor\" href=\"#enter-the-admin-site\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Essayez maintenant de vous connecter avec le compte administrateur que vous avez créé à l’étape précédente. Vous devriez voir apparaître la page d’accueil du site d’administration de Django :</p>\n<img alt=\"Django admin index page\" src=\"/fr/3.2/_images/admin02.png\" />\n<p>Vous devriez voir quelques types de contenu éditable : groupes et utilisateurs. Ils sont fournis par <a class=\"reference internal\" href=\"/fr/3.2/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code></a>, le système d’authentification livré avec Django.</p>\n</section>\n<section id=\"make-the-poll-app-modifiable-in-the-admin\">\n<h3>Rendre l’application de sondage modifiable via l’interface d’admin<a class=\"heading-anchor\" href=\"#make-the-poll-app-modifiable-in-the-admin\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Mais où est notre application de sondage ? Elle n’est pas affichée sur la page d’index de l’interface d’administration.</p>\n<p>Plus qu’une chose à faire : il faut indiquer à l’admin que les objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> ont une interface d’administration. Pour ceci, ouvrez le fichier <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/admin.py</span></code> et éditez-le de la manière suivante :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/admin.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">)</span>\n</code></pre></figure>\n</section>\n<section id=\"explore-the-free-admin-functionality\">\n<h3>Exploration des fonctionnalités de l’interface d’administration<a class=\"heading-anchor\" href=\"#explore-the-free-admin-functionality\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Maintenant que nous avons inscrit <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> dans l’interface d’administration, Django sait que cela doit apparaître sur la page d’index :</p>\n<img alt=\"Django admin index page, now with polls displayed\" src=\"/fr/3.2/_images/admin03t.png\" />\n<p>Cliquez sur « Questions ». À présent, vous êtes sur la page « liste pour modification » des questions. Cette page affiche toutes les questions de la base de données et vous permet d’en choisir une pour la modifier. Il y a la question « Quoi de neuf ? » que nous avons créée précédemment :</p>\n<img alt=\"Polls change list page\" src=\"/fr/3.2/_images/admin04t.png\" />\n<p>Cliquez sur la question « Quoi de neuf ? » pour la modifier :</p>\n<img alt=\"Editing form for question object\" src=\"/fr/3.2/_images/admin05t.png\" />\n<p>À noter ici :</p>\n<ul class=\"simple\">\n<li><p>Le formulaire est généré automatiquement à partir du modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>.</p></li>\n<li><p>Les différents types de champs du modèle (<a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a>, <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a>) correspondent au composant graphique d’entrée HTML approprié. Chaque type de champ sait comment s’afficher dans l’interface d’administration de Django.</p></li>\n<li><p>Chaque <a class=\"reference internal\" href=\"/fr/3.2/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> reçoit automatiquement des raccourcis Javascript. Les dates obtiennent un raccourci « Aujourd’hui » et un calendrier en popup, et les heures obtiennent un raccourci « Maintenant » et une popup pratique qui liste les heures couramment saisies.</p></li>\n</ul>\n<p>La partie inférieure de la page vous propose une série d’opérations :</p>\n<ul class=\"simple\">\n<li><p>Enregistrer – Enregistre les modifications et retourne à la page liste pour modification de ce type d’objet.</p></li>\n<li><p>Enregistrer et continuer les modifications – Enregistre les modifications et recharge la page d’administration de cet objet.</p></li>\n<li><p>Enregistrer et ajouter un nouveau – Enregistre les modifications et charge un nouveau formulaire vierge pour ce type d’objet.</p></li>\n<li><p>Supprimer – Affiche une page de confirmation de la suppression.</p></li>\n</ul>\n<p>Si la valeur de « Date de publication » ne correspond pas à l’heure à laquelle vous avez créé cette question dans le <a class=\"reference internal\" href=\"/fr/3.2/intro/tutorial01/\"><span class=\"doc\">tutoriel 1</span></a>, vous avez probablement oublié de définir la valeur correcte du paramètre <a class=\"reference internal\" href=\"/fr/3.2/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a>. Modifiez-le, rechargez la page et vérifiez que la bonne valeur s’affiche.</p>\n<p>Modifiez la « Date de publication » en cliquant sur les raccourcis « Aujourd’hui » et « Maintenant ». Puis cliquez sur « Enregistrer et continuer les modifications ». Ensuite, cliquez sur « Historique » en haut à droite de la page. Vous verrez une page listant toutes les modifications effectuées sur cet objet via l’interface d’administration de Django, accompagnées des date et heure, ainsi que du nom de l’utilisateur qui a fait ce changement :</p>\n<img alt=\"History page for question object\" src=\"/fr/3.2/_images/admin06t.png\" />\n<p>Lorsque vous serez à l’aise avec l’API des modèles et que vous vous serez familiarisé avec le site d’administration, lisez la <a class=\"reference internal\" href=\"/fr/3.2/intro/tutorial03/\"><span class=\"doc\">partie 3 de ce tutoriel</span></a> pour apprendre comment ajouter davantage de vues à notre application de sondage.</p>\n</section>\n</section>","rootId":"writing-your-first-django-app-part-2","toc":[{"title":"Configuration de la base de données","anchor":"database-setup","children":[]},{"title":"Création des modèles","anchor":"creating-models","children":[]},{"title":"Activation des modèles","anchor":"activating-models","children":[]},{"title":"Jouer avec l’interface de programmation (API)","anchor":"playing-with-the-api","children":[]},{"title":"Introduction au site d’administration de Django","anchor":"introducing-the-django-admin","children":[{"title":"Création d’un utilisateur administrateur","anchor":"creating-an-admin-user","children":[]},{"title":"Démarrage du serveur de développement","anchor":"start-the-development-server","children":[]},{"title":"Entrée dans le site d’administration","anchor":"enter-the-admin-site","children":[]},{"title":"Rendre l’application de sondage modifiable via l’interface d’admin","anchor":"make-the-poll-app-modifiable-in-the-admin","children":[]},{"title":"Exploration des fonctionnalités de l’interface d’administration","anchor":"explore-the-free-admin-functionality","children":[]}]}],"breadcrumbs":[{"docname":"intro/index","title":"Premiers pas","url":"/fr/3.2/intro/"}],"prev":{"docname":"intro/tutorial01","title":"Écriture de votre première application Django, 1ère partie","url":"/fr/3.2/intro/tutorial01/"},"next":{"docname":"intro/tutorial03","title":"Écriture de votre première application Django, 3ème partie","url":"/fr/3.2/intro/tutorial03/"},"formats":{"html":"/fr/3.2/intro/tutorial02/","markdown":"/fr/3.2/intro/tutorial02.md","json":"/fr/3.2/intro/tutorial02.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/intro/tutorial02.txt","official":"https://docs.djangoproject.com/fr/3.2/intro/tutorial02/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}