{"title":"Utilisation de mixins avec les vues fondées sur les classes","version":"5.1","locale":"fr","docname":"topics/class-based-views/mixins","url":"/fr/5.1/topics/class-based-views/mixins/","canonical":"https://djangodocs.dev/fr/5.1/topics/class-based-views/mixins/","summary":"Prudence Ceci est un sujet avancé. Nous suggérons d’avoir une bonne connaissance préalable des vues Django fondées sur les classes avant d’explorer ces techniques.…","html":"<h1>Utilisation de mixins avec les vues fondées sur les classes<a class=\"heading-anchor\" href=\"#using-mixins-with-class-based-views\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"admonition admonition-caution\" role=\"note\">\n<p class=\"admonition-title\">Prudence</p>\n<p>Ceci est un sujet avancé. Nous suggérons d’avoir une bonne connaissance préalable des <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/\"><span class=\"doc\">vues Django fondées sur les classes</span></a> avant d’explorer ces techniques.</p>\n</aside>\n<p>Les vues fondées sur les classes intégrées dans Django fournissent de nombreuses fonctionnalités, mais certaines d’entre elles pourraient être utiles de manière indépendante. Par exemple, si l’on écrit une vue qui utilise un gabarit pour produire une réponse HTTP, mais sans utiliser <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/base/#django.views.generic.base.TemplateView\" title=\"django.views.generic.base.TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a>; ou encore si l’on veut utiliser un gabarit seulement pour une requête <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> et faire quelque chose de totalement différent pour les requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code>. Même si on pourrait utiliser directement <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a>, on se retrouverait avec pas mal de code dupliqué.</p>\n<p>C’est pour cette raison que Django fournit aussi un certain nombre de mixins englobant des fonctionnalités de manière distincte. Le rendu de gabarits, par exemple, est isolé dans la classe <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a>. La documentation de référence de Django contient une <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins/\"><span class=\"doc\">documentation complète de toutes les classes mixins</span></a>.</p>\n<section id=\"context-and-template-responses\">\n<h2>Contexte et réponses par gabarit<a class=\"heading-anchor\" href=\"#context-and-template-responses\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Deux classes mixins centrales sont à disposition pour aider à présenter une interface cohérente pour travailler avec les gabarits dans les vues fondées sur les classes.</p>\n<dl>\n<dt><a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a></dt><dd><p>Chaque vue intégrée renvoyant une réponse <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> appelle la méthode <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a> fournie par <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code>. Dans la plupart des cas, cet appel se fait automatiquement (par exemple, elle est appelée par la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> aussi bien de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/base/#django.views.generic.base.TemplateView\" title=\"django.views.generic.base.TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> que de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>). De même, il est peu probable que vous ayez besoin de la surcharger, bien que cela peut se révéler utile si vous voulez que la réponse renvoie du contenu non rendu par un gabarit Django. Vous pouvez trouver un exemple d’un tel usage dans <a class=\"reference internal\" href=\"#jsonresponsemixin-example\"><span class=\"std std-ref\">l’exemple JSONResponseMixin</span></a>.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code> appelle elle-même <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names\" title=\"django.views.generic.base.TemplateResponseMixin.get_template_names\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code></a> qui consulte l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.template_name\" title=\"django.views.generic.base.TemplateResponseMixin.template_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name</span></code></a> de la vue, par défaut. Deux autres mixins (<a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectTemplateResponseMixin</span></code></a>) surchargent cette méthode pour offrir des valeurs par défaut plus souples lorsqu’il s’agit de manipuler des objets réels.</p>\n</dd>\n<dt><a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin\" title=\"django.views.generic.base.ContextMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ContextMixin</span></code></a></dt><dd><p>Chaque vue intégrée nécessitant des données de contexte, comme pour effectuer le rendu d’un gabarit (y compris <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code> ci-dessus), doit appeler <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a> en transmettant sous forme de paramètres nommés les données qu’elle souhaite y placer. <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> renvoie un dictionnaire ; dans <code class=\"docutils literal notranslate\"><span class=\"pre\">ContextMixin</span></code>, elle renvoie ses paramètres nommés, mais il est fréquent de surcharger cela pour ajouter davantage de contenu dans ce dictionnaire. Vous pouvez également utiliser l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.extra_context\" title=\"django.views.generic.base.ContextMixin.extra_context\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">extra_context</span></code></a>.</p>\n</dd>\n</dl>\n</section>\n<section id=\"building-up-django-s-generic-class-based-views\">\n<h2>Construction des vues fondées sur les classes de Django<a class=\"heading-anchor\" href=\"#building-up-django-s-generic-class-based-views\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Voyons comment deux des vues fondées sur les classes de Django sont construites à partir de mixins fournissant des fonctionnalités isolées. Nous examinerons <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> qui produit une vue de détail d’un objet et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> qui produit une liste d’objets, généralement à partir d’un jeu de requête, avec pagination facultative. Ceci nous amènera à étudier quatre mixins qui, combinées entre elles, fournissent des fonctionnalités utiles lors du traitement d’un objet Django unique ou d’un ensemble d’objets.</p>\n<p>Il existe également des classes mixins dans les vues génériques d’édition (<a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView\" title=\"django.views.generic.edit.FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> et les vues spécifiques aux modèles <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView\" title=\"django.views.generic.edit.CreateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CreateView</span></code></a>, <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView\" title=\"django.views.generic.edit.UpdateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UpdateView</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView\" title=\"django.views.generic.edit.DeleteView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DeleteView</span></code></a>), ainsi que dans les vues génériques centrées sur les dates. Ces classes sont décrites dans la <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins/\"><span class=\"doc\">documentation de référence des mixins</span></a>.</p>\n<section id=\"detailview-working-with-a-single-django-object\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code>: traitement d’un seul objet Django<a class=\"heading-anchor\" href=\"#detailview-working-with-a-single-django-object\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour afficher le détail d’un objet, il y a fondamentalement deux choses à faire : récupérer l’objet, puis produire une réponse <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> à l’aide du gabarit adéquat, en transmettant l’objet dans le contexte.</p>\n<p>Pour obtenir l’objet, <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> se base sur <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> qui fournit une méthode <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a> qui va rechercher l’objet en se basant sur l’URL de la requête (elle cherche les paramètres nommés <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">slug</span></code> tels que déclarés dans la configuration d’URL et sélectionne l’objet en utilisant soit l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.model\" title=\"django.views.generic.detail.SingleObjectMixin.model\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">model</span></code></a> de la vue, soit l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.queryset\" title=\"django.views.generic.detail.SingleObjectMixin.queryset\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">queryset</span></code></a> si celui-ci est présent). <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> surcharge aussi <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a>, qui est utilisée dans toutes les vues fondées sur les classes de Django pour fournir les données de contexte servant au rendu des gabarits.</p>\n<p>Pour produire la réponse <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a>, <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> utilise <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a>, qui étend <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a>, surchargeant <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names\" title=\"django.views.generic.base.TemplateResponseMixin.get_template_names\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code></a> comme expliqué plus haut. Il fournit en réalité un bon nombre d’options élaborées, mais le nom que la plupart des gens vont utiliser est <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;étiquette_application&gt;/&lt;nom_modèle&gt;_detail.html</span></code>. La partie <code class=\"docutils literal notranslate\"><span class=\"pre\">_detail</span></code> peut être modifiée en définissant un attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name_suffix</span></code></a> différent dans une sous-classe (par exemple, les <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/generic-editing/\"><span class=\"doc\">vues génériques d’édition</span></a> emploient <code class=\"docutils literal notranslate\"><span class=\"pre\">_form</span></code> pour les vues de création et de mise à jour et <code class=\"docutils literal notranslate\"><span class=\"pre\">_confirm_delete</span></code> pour les vues de suppression).</p>\n</section>\n<section id=\"listview-working-with-many-django-objects\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">ListView</span></code>: traitement de plusieurs objets Django<a class=\"heading-anchor\" href=\"#listview-working-with-many-django-objects\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Les listes d’objets suivent grosso modo le même modèle : récupérer d’abord une liste d’objets (potentiellement paginés), typiquement un objet <a class=\"reference internal\" href=\"/fr/5.1/ref/models/querysets/#django.db.models.query.QuerySet\" title=\"django.db.models.query.QuerySet\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code></a>, puis produire une réponse <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> avec le gabarit adéquat pour exploiter cette liste d’objets.</p>\n<p>Pour obtenir les objets, <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> utilise <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> qui offre à la fois <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.paginate_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.paginate_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">paginate_queryset()</span></code></a>. Au contraire de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>, il n’est pas nécessaire d’identifier des éléments d’URL pour déterminer le jeu de requête à traiter ; le comportement par défaut est d’utiliser l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.queryset\" title=\"django.views.generic.list.MultipleObjectMixin.queryset\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">queryset</span></code></a> ou <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.model\" title=\"django.views.generic.list.MultipleObjectMixin.model\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">model</span></code></a> de la classe de vue. Une raison fréquente de vouloir surcharger ici <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code></a> est d’adapter la liste d’objets de manière dynamique, par exemple en fonction de l’utilisateur actuel ou pour exclure des articles dont la date est dans le futur dans un blog.</p>\n<p><a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> surcharge aussi <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a> pour inclure les variables de contexte appropriées à la pagination (indiquant des valeurs vides si la pagination est désactivée). Elle compte sur la présence de <code class=\"docutils literal notranslate\"><span class=\"pre\">object_list</span></code> dans les paramètres nommés transmis, ce dont se charge  <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a>.</p>\n<p>Pour produire une réponse <a class=\"reference internal\" href=\"/fr/5.1/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a>, <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> utilise ensuite <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectTemplateResponseMixin</span></code></a>; comme pour <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> ci-dessus, <code class=\"docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code> est surchargée pour fournir une <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">série</span> <span class=\"pre\">d'options</span></code></a> dont la plus utilisée est le nom de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;étiquette_application&gt;/&lt;nom_modèle&gt;_list.html</span></code> où la partie <code class=\"docutils literal notranslate\"><span class=\"pre\">_list</span></code> provient aussi de l’attribut <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name_suffix</span></code></a> (les vues génériques centrées sur les dates utilisent des suffixes tels que <code class=\"docutils literal notranslate\"><span class=\"pre\">_archive</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">_archive_year</span></code>, etc. pour utiliser différents gabarits correspondant aux différentes vues de listes spécialisées pour les dates).</p>\n</section>\n</section>\n<section id=\"using-django-s-class-based-view-mixins\">\n<h2>Utilisation des mixins de vues fondées sur les classes de Django<a class=\"heading-anchor\" href=\"#using-django-s-class-based-view-mixins\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Maintenant que nous avons vu comment les classes génériques fondées sur les classes de Django utilisent les mixins à disposition, examinons d’autres façons de les combiner. Nous allons toujours les combiner avec d’autres vues intégrées ou génériques fondées sur les classes, mais les cas d’utilisation auxquels Django répond ne recouvrent pas toutes les situations plus rares auxquelles on peut être confronté.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>On ne peut pas combiner tous les mixins, ni combiner n’importe quel mixin avec toutes les vues génériques fondées sur les classes. Nous présentons ici quelques exemples qui fonctionnent ; si vous souhaitez construire d’autres fonctionnalités, vous devrez étudier les interactions entre les attributs et les méthodes qui se chevauchent entre les différentes classes utilisées, ainsi que la façon dont <a class=\"reference external\" href=\"https://www.python.org/download/releases/2.3/mro/\">l’ordre de résolution des méthodes</a> affecte la version des méthodes appelée et l’ordre de ces appels.</p>\n<p>La documentation de référence des  <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/\"><span class=\"doc\">vues fondées sur les classes</span></a> et des  <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins/\"><span class=\"doc\">mixins de vues fondées sur les classes</span></a> de Django vous aidera à comprendre quels attributs et méthodes peuvent être la source de conflits entre les différentes classes et mixins.</p>\n<p>Dans le doute, il est souvent préférable de simplifier les choses en se basant sur <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#View\" title=\"View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> ou <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a>, peut-être avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> ou <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a>. Même si vous devez finalement écrire un peu plus de code, il sera probablement plus compréhensible pour quelqu’un devant s’y atteler plus tard, et en réduisant les interactions à surveiller, vous vous économiserez un peu de temps de réflexion (il est bien sûr toujours possible de se plonger dans l’implémentation de Django des vues génériques fondées sur les classes pour y chercher de l’inspiration sur la façon de traiter les problèmes).</p>\n</aside>\n<section id=\"using-singleobjectmixin-with-view\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> avec <code class=\"docutils literal notranslate\"><span class=\"pre\">View</span></code><a class=\"heading-anchor\" href=\"#using-singleobjectmixin-with-view\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si nous voulons écrire une classe de vue ne répondant qu’aux requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code>, nous héritons de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/base/#django.views.generic.base.View\" title=\"django.views.generic.base.View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> et écrivons une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> dans la sous-classe. Cependant, si le traitement doit porter sur un objet particulier identifié par l’URL, il est souhaitable de profiter de la fonctionnalité offerte par <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>.</p>\n<p>Nous allons démontrer cela avec le modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> que nous avons utilisé dans <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/generic-display/\"><span class=\"doc\">l’introduction aux vues génériques basées sur les classes</span></a>.</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\">views.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.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span><span class=\"p\">,</span> <span class=\"n\">HttpResponseRedirect</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">View</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">RecordInterestView</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;Records the current user&#39;s interest in an author.&quot;&quot;&quot;</span>\n\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">HttpResponseForbidden</span><span class=\"p\">()</span>\n\n        <span class=\"c1\"># Look up the author we&#39;re interested in.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"c1\"># Actually record interest somehow here!</span>\n\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponseRedirect</span><span class=\"p\">(</span>\n            <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s2\">&quot;author-detail&quot;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">})</span>\n        <span class=\"p\">)</span>\n</code></pre></figure>\n<p>En pratique, l’intérêt devrait probablement être enregistré dans un stockage clé-valeur plutôt que dans une base de données relationnelle, nous avons donc laissé cet aspect de côté. La seule partie de la vue qui peut profiter de l’utilisation de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> est l’endroit où il s’agit de récupérer l’auteur concerné par l’intérêt, ce qui est fait en appelant <code class=\"docutils literal notranslate\"><span class=\"pre\">self.get_object()</span></code>. Tout le reste est pris en charge pour nous par le mixin.</p>\n<p>Nous pouvons assez facilement brancher cette vue dans nos URL :</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\">urls.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.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">path</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">RecordInterestView</span>\n\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span>\n        <span class=\"s2\">&quot;author/&lt;int:pk&gt;/interest/&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">RecordInterestView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(),</span>\n        <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;author-interest&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Remarquez le groupe nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> qui sera utilisé par <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a> pour rechercher l’instance <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code>. Il est aussi possible d’utiliser un « slug » ou toute autre fonctionnalité de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>.</p>\n</section>\n<section id=\"using-singleobjectmixin-with-listview\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> avec <code class=\"docutils literal notranslate\"><span class=\"pre\">ListView</span></code><a class=\"heading-anchor\" href=\"#using-singleobjectmixin-with-listview\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> intègre la pagination, mais il peut être par exemple souhatiable de paginer une liste d’objets qui sont tous liés (par clé étrangère) à un autre objet. Dans notre exemple de publication, on pourrait vouloir paginer tous les livres d’un éditeur particulier.</p>\n<p>Une façon de faire cela serait de combiner <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>, afin que le jeu de requête de la liste de livres paginée puisse dépendre de l’éditeur trouvé comme objet unique. Afin de faire cela, il est nécessaire d’avoir deux jeux de requête différents :</p>\n<dl class=\"simple\">\n<dt>Le jeu de requête <code class=\"docutils literal notranslate\"><span class=\"pre\">Book</span></code> utilisé par <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a></dt><dd><p>Comme nous avons accès à l’éditeur <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> des livres que nous souhaitons afficher, nous surchargeons <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> et utilisons le <a class=\"reference internal\" href=\"/fr/5.1/topics/db/queries/#backwards-related-objects\"><span class=\"std std-ref\">gestionnaire inverse de clé étrangère</span></a> de l’objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code>.</p>\n</dd>\n<dt>Le jeu de requête <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> utilisé par <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a></dt><dd><p>Nous comptons sur l’implémentation par défaut de <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</span></code> pour récupérer le bon objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code>. Cependant, nous devons explicitement transmettre un paramètre <code class=\"docutils literal notranslate\"><span class=\"pre\">queryset</span></code> car sinon, l’implémentation par défaut de <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</span></code>  appellerait <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> que nous avons surchargée pour renvoyer des objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Book</span></code> au lieu d’objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code>.</p>\n</dd>\n</dl>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Il faut être prudent avec <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code>. Comme les deux classes <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> vont placer des éléments dans les données de contexte sous la valeur <code class=\"docutils literal notranslate\"><span class=\"pre\">context_object_name</span></code>, si elle est définie, nous allons plutôt nous assurer de manière explicite que l’objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> se trouve bien dans les données de contexte. <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> se chargera d’ajouter les contenus <code class=\"docutils literal notranslate\"><span class=\"pre\">page_obj</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">paginator</span></code> adéquats pour autant que nous n’oubliions pas d’appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code>.</p>\n</aside>\n<p>Nous pouvons maintenant écrire une nouvelle vue <code class=\"docutils literal notranslate\"><span class=\"pre\">PublisherDetailView</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ListView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Publisher</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PublisherDetailView</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">ListView</span><span class=\"p\">):</span>\n    <span class=\"n\">paginate_by</span> <span class=\"o\">=</span> <span class=\"mi\">2</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;books/publisher_detail.html&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">(</span><span class=\"n\">queryset</span><span class=\"o\">=</span><span class=\"n\">Publisher</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=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_context_data</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s2\">&quot;publisher&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</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\">object</span><span class=\"o\">.</span><span class=\"n\">book_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Remarquez notre manière de définir <code class=\"docutils literal notranslate\"><span class=\"pre\">self.object</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> afin que nous puissions ensuite l’utiliser dans <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code>. Si vous ne définissez pas <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code>, le nom du gabarit prendra la valeur par défaut choisie par <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a>, ce qui donnera dans ce cas <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;books/book_list.html&quot;</span></code> car il s’agit d’une liste de livres. <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> n’a pas conscience de la présence de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>, elle ne sait donc pas du tout que cette vue a quelque chose à voir avec un objet <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code>.</p>\n<p>Nous avons délibérément défini <code class=\"docutils literal notranslate\"><span class=\"pre\">paginate_by</span></code> à un petit nombre dans l’exemple afin que vous n’ayez pas à créer beaucoup de livres pour voir la pagination à l’œuvre ! Voici le gabarit que vous pourriez utiliser :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">&quot;base.html&quot;</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">content</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>Publisher <span class=\"cp\">{{</span> <span class=\"nv\">publisher.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>\n\n    <span class=\"p\">&lt;</span><span class=\"nt\">ol</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">book</span> <span class=\"k\">in</span> <span class=\"nv\">page_obj</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">book.title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">ol</span><span class=\"p\">&gt;</span>\n\n    <span class=\"p\">&lt;</span><span class=\"nt\">div</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;pagination&quot;</span><span class=\"p\">&gt;</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">span</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;step-links&quot;</span><span class=\"p\">&gt;</span>\n            <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">page_obj.has_previous</span> <span class=\"cp\">%}</span>\n                <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;?page=</span><span class=\"cp\">{{</span> <span class=\"nv\">page_obj.previous_page_number</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>previous<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n            <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n\n            <span class=\"p\">&lt;</span><span class=\"nt\">span</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;current&quot;</span><span class=\"p\">&gt;</span>\n                Page <span class=\"cp\">{{</span> <span class=\"nv\">page_obj.number</span> <span class=\"cp\">}}</span> of <span class=\"cp\">{{</span> <span class=\"nv\">paginator.num_pages</span> <span class=\"cp\">}}</span>.\n            <span class=\"p\">&lt;/</span><span class=\"nt\">span</span><span class=\"p\">&gt;</span>\n\n            <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">page_obj.has_next</span> <span class=\"cp\">%}</span>\n                <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;?page=</span><span class=\"cp\">{{</span> <span class=\"nv\">page_obj.next_page_number</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>next<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n            <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;/</span><span class=\"nt\">span</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">div</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"avoid-anything-more-complex\">\n<h2>Risque de trop grande complexité<a class=\"heading-anchor\" href=\"#avoid-anything-more-complex\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Généralement, il est possible d’utiliser <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> lorsque leurs fonctionnalités sont nécessaires. Comme montré plus haut, en prenant certaines précautions, on peut même combiner <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a>. Cependant, les choses deviennent de plus en plus complexes avec ces combinaisons ; voici une bonne règle générale :</p>\n<aside class=\"admonition admonition-hint\">\n<p class=\"admonition-title\">Indication</p>\n<p>Chacune de vos vues ne devrait utiliser que des mixins ou des vues en provenance de l’un des groupes de vues génériques fondées sur les classes : <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/generic-display/\"><span class=\"doc\">détail, liste</span></a>, <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/generic-editing/\"><span class=\"doc\">édition</span></a> et date. Par exemple, il est convenable de combiner <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> (vue intégrée) avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> (liste générique), mais vous rencontrerez sûrement des problèmes si vous combinez <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> (détail générique) avec <code class=\"docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code> (liste générique).</p>\n</aside>\n<p>Pour montrer ce qui arrive quand on essaie de trop compliquer, nous présentons un exemple qui sacrifie la lisibilité et la maintenabilité alors qu’il existe une solution plus simple. Examinons d’abord une tentative naïve de combiner <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> pour permettre l’envoi <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> par un formulaire <a class=\"reference internal\" href=\"/fr/5.1/ref/forms/api/#django.forms.Form\" title=\"django.forms.Form\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Form</span></code></a> Django vers la même URL qui est utilisée pour afficher un objet avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>.</p>\n<section id=\"using-formmixin-with-detailview\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code> avec <code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code><a class=\"heading-anchor\" href=\"#using-formmixin-with-detailview\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Rappelez-vous notre exemple précédent qui combinait <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#View\" title=\"View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a>. Nous enregistrions l’intérêt d’un utilisateur pour un auteur particulier. Admettons que nous voulions maintenant donner la possibilité d’écrire un message motivant leur intérêt. Nous partons encore une fois du principe que nous ne stockerons pas cela dans une base de données relationnelle, mais plutôt dans quelque chose de plus exotique dont nous ne nous soucierons pas dans cet exemple.</p>\n<p>À ce stade, il est naturel de faire appel à un formulaire <a class=\"reference internal\" href=\"/fr/5.1/ref/forms/api/#django.forms.Form\" title=\"django.forms.Form\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Form</span></code></a> pour englober les informations envoyées par le navigateur de l’utilisateur vers Django. En admettant que nous adhérons aussi aux principes de <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Representational_state_transfer\">REST</a>, nous aimerions utiliser la même URL pour l’affichage de l’auteur que pour la capture du message en provenance de l’utilisateur. Réécrivons notre vue <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetailView</span></code> dans cette optique.</p>\n<p>Nous conserverons le traitement <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> de la classe <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>, même s’il faudra rajouter un formulaire <a class=\"reference internal\" href=\"/fr/5.1/ref/forms/api/#django.forms.Form\" title=\"django.forms.Form\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Form</span></code></a> dans les données de contexte pour pouvoir l’afficher dans le gabarit. Nous allons aussi profiter du traitement de formulaire de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> et écrire un peu de code afin qu’en cas d’envoi <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code>, le formulaire soit instancié de manière appropriée.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Nous utilisons <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> et implémentons nous-même la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> plutôt que d’essayer de mélanger <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> (qui fournit déjà une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> exploitable), parce que ces deux vues implémentent <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> et que cela risquerait d’ajouter de la confusion.</p>\n</aside>\n<p>Voici à quoi ressemble notre nouvelle vue <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetailView</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=\"c1\"># CAUTION: you almost certainly do not want to do this.</span>\n<span class=\"c1\"># It is provided as part of a discussion of problems you can</span>\n<span class=\"c1\"># run into when combining different generic class-based view</span>\n<span class=\"c1\"># functionality that is not designed to be used together.</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">forms</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DetailView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.edit</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">FormMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterestForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">Form</span><span class=\"p\">):</span>\n    <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">()</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorDetailView</span><span class=\"p\">(</span><span class=\"n\">FormMixin</span><span class=\"p\">,</span> <span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n    <span class=\"n\">form_class</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_success_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s2\">&quot;author-detail&quot;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">})</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">HttpResponseForbidden</span><span class=\"p\">()</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"n\">form</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_form</span><span class=\"p\">()</span>\n        <span class=\"k\">if</span> <span class=\"n\">form</span><span class=\"o\">.</span><span class=\"n\">is_valid</span><span class=\"p\">():</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">form_valid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">form_invalid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">form_valid</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">form</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Here, we would record the user&#39;s interest using the message</span>\n        <span class=\"c1\"># passed in form.cleaned_data[&#39;message&#39;]</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">form_valid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_success_url()</span></code> sert à indiquer une destination de redirection, ce qui est utilisé dans l’implémentation par défaut de <code class=\"docutils literal notranslate\"><span class=\"pre\">form_valid()</span></code>. Nous devons fournir notre propre méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code>, comme expliqué précédemment.</p>\n</section>\n<section id=\"a-better-solution\">\n<h3>Une meilleure solution<a class=\"heading-anchor\" href=\"#a-better-solution\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le nombre d’interactions subtiles entre <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> et <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> éprouve déjà nos capacités conceptuelles. Il est improbable que vous ayez envie d’écrire vous-même ce genre de classe.</p>\n<p>Dans ce cas, vous pourriez écrire vous-même la méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code>, en conservant <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> comme seule fonctionnalité générique, même si l’écriture du code de gestion des formulaires implique beaucoup de duplication.</p>\n<p>Sinon, une approche certainement plus économique que ci-dessus serait d’avoir une vue séparée pour le traitement du formulaire, ce qui permettrait d’utiliser sans problème <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView\" title=\"django.views.generic.edit.FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> séparément de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>.</p>\n</section>\n<section id=\"an-alternative-better-solution\">\n<h3>Une meilleure solution alternative<a class=\"heading-anchor\" href=\"#an-alternative-better-solution\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>En réalité, ce que nous essayons de faire ici est d’utiliser deux vues classes différentes pour la même URL. Pourquoi donc ne pas simplement faire cela ? La division est ici très claire : les requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> devraient aboutir à la vue <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> (avec en plus le formulaire dans les données de contexte) et les requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> à la vue <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a>.  Mettons d’abord en place ces deux vues.</p>\n<p>La vue <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetailView</span></code> est presque la même que <a class=\"reference internal\" href=\"/fr/5.1/topics/class-based-views/generic-display/#generic-views-extra-work\"><span class=\"std std-ref\">celle que nous avons présentée en introduction</span></a>. Nous devons écrire notre propre méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> pour mettre à disposition <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterestForm</span></code> dans le gabarit. Nous omettons la surcharge de <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</span></code> de la version précédente par souci de clarté :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">forms</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DetailView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterestForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">Form</span><span class=\"p\">):</span>\n    <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">()</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorDetailView</span><span class=\"p\">(</span><span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_context_data</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s2\">&quot;form&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n</code></pre></div>\n<p>Puis pour <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterestFormView</span></code>, il s’agit d’une sous-classe de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a>, mais nous devons y adjoindre <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> pour pouvoir obtenir l’auteur concerné par l’action en cours et ne pas oublier de définir <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> pour s’assurer que les erreurs de formulaires soient affichées dans le même gabarit que <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetailView</span></code> utilise lors de la requête <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">FormView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterestFormView</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">FormView</span><span class=\"p\">):</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;books/author_detail.html&quot;</span>\n    <span class=\"n\">form_class</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">HttpResponseForbidden</span><span class=\"p\">()</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_success_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s2\">&quot;author-detail&quot;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">})</span>\n</code></pre></div>\n<p>Pour terminer, nous lions le tout en créant une nouvelle vue <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorView</span></code>. Nous savons déjà que l’appel à <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">as_view()</span></code></a> sur une vue fondée sur les classes nous renvoie un objet se comportant exactement comme une vue de type fonction. Nous pouvons donc effectuer cet appel au moment où il faut choisir entre les deux « sous-vues ».</p>\n<p>Vous pouvez transmettre des paramètres nommés à <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">as_view()</span></code></a> comme vous le feriez dans la configuration d’URL, par exemple si vous vouliez que le comportement de <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterestFormView</span></code> puisse aussi être utilisé avec une autre URL mais en affichant un gabarit différent :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">View</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorView</span><span class=\"p\">(</span><span class=\"n\">View</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">view</span> <span class=\"o\">=</span> <span class=\"n\">AuthorDetailView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">view</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestFormView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Cette approche peut également être employée avec toute autre vue fondée sur les classes, générique ou créée par vos soins, héritant directement de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#View\" title=\"View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> ou de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a>, car elle conserve les différentes vues aussi distinctes que possible.</p>\n</section>\n</section>\n<section id=\"more-than-just-html\">\n<span id=\"jsonresponsemixin-example\"></span><h2>Plus que du simple code HTML<a class=\"heading-anchor\" href=\"#more-than-just-html\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Les vues fondées sur les classes se révèlent particulièrement utiles au moment où l’on a besoin de répéter plusieurs fois un processus semblable. Imaginez qu’il faille écrire une API et que chaque vue doive renvoyer du JSON au lieu de produire une page HTML.</p>\n<p>Il est alors possible de créer une classe mixin afin de l’utiliser dans chaque vue, gérant ainsi à un seul endroit la conversion vers le format JSON.</p>\n<p>Par exemple, une classe mixin pour JSON pourrait ressembler à ceci :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">JsonResponse</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONResponseMixin</span><span class=\"p\">:</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    A mixin that can be used to render a JSON response.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_json_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Returns a JSON response, transforming &#39;context&#39; to make the payload.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">JsonResponse</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_data</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">),</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Returns an object that will be serialized as JSON by json.dumps().</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"c1\"># Note: This is *EXTREMELY* naive; in reality, you&#39;ll need</span>\n        <span class=\"c1\"># to do much more complex handling to ensure that arbitrary</span>\n        <span class=\"c1\"># objects -- such as Django model instances or querysets</span>\n        <span class=\"c1\"># -- can be serialized as JSON.</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Consultez la documentation <a class=\"reference internal\" href=\"/fr/5.1/topics/serialization/\"><span class=\"doc\">Sérialisation d’objets Django</span></a> pour plus d’informations sur la façon de transformer correctement des modèles Django et des jeux de requête au format JSON.</p>\n</aside>\n<p>Ce mixin fournit une méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_json_response()</span></code> ayant la même signature que <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a>. Pour l’utiliser, nous devons la combiner par exemple à une classe <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code> et surcharger <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code> afin d’appeler <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_json_response()</span></code> à la place :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TemplateView</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONView</span><span class=\"p\">(</span><span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">TemplateView</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Il serait aussi possible d’utiliser cette classe mixin avec l’une des vues génériques. On peut composer sa propre version de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> en combinant <code class=\"docutils literal notranslate\"><span class=\"pre\">JSONResponseMixin</span></code> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.BaseDetailView\" title=\"django.views.generic.detail.BaseDetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BaseDetailView</span></code></a> (celle-ci contenant le comportement de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> avant le rendu du gabarit) :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseDetailView</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONDetailView</span><span class=\"p\">(</span><span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">BaseDetailView</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Cette vue peut ensuite être déployée de la même façon que pour n’importe quelle vue <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>, reproduisant le même comportement à l’exception du format de la réponse.</p>\n<p>Si vous avez de réels goûts d’aventure, vous pourriez même tenter de combiner avec une sous-classe de   <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> capable de renvoyer <em>à la fois</em> du contenu HTML et JSON en fonction d’une propriété de la requête HTTP, telle qu’un paramètre de requête ou un en-tête HTTP. Combinez <code class=\"docutils literal notranslate\"><span class=\"pre\">JSONResponseMixin</span></code> avec <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> et surchargez l’implémentation de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a> pour déléguer le rendu à la méthode appropriée en fonction du type de réponse demandée par l’utilisateur :</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectTemplateResponseMixin</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HybridDetailView</span><span class=\"p\">(</span>\n    <span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">SingleObjectTemplateResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">BaseDetailView</span>\n<span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Look for a &#39;format=json&#39; GET argument</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">GET</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;format&quot;</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"s2\">&quot;json&quot;</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">render_to_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>En raison de la façon dont Python résout la surcharge des méthodes, l’appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">super().render_to_response(context)</span></code> fait en réalité appel à l’implémentation <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a> de <a class=\"reference internal\" href=\"/fr/5.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a>.</p>\n</section>","rootId":"using-mixins-with-class-based-views","toc":[{"title":"Contexte et réponses par gabarit","anchor":"context-and-template-responses","children":[]},{"title":"Construction des vues fondées sur les classes de Django","anchor":"building-up-django-s-generic-class-based-views","children":[{"title":"DetailView: traitement d’un seul objet Django","anchor":"detailview-working-with-a-single-django-object","children":[]},{"title":"ListView: traitement de plusieurs objets Django","anchor":"listview-working-with-many-django-objects","children":[]}]},{"title":"Utilisation des mixins de vues fondées sur les classes de Django","anchor":"using-django-s-class-based-view-mixins","children":[{"title":"Utilisation de SingleObjectMixin avec View","anchor":"using-singleobjectmixin-with-view","children":[]},{"title":"Utilisation de SingleObjectMixin avec ListView","anchor":"using-singleobjectmixin-with-listview","children":[]}]},{"title":"Risque de trop grande complexité","anchor":"avoid-anything-more-complex","children":[{"title":"Utilisation de FormMixin avec DetailView","anchor":"using-formmixin-with-detailview","children":[]},{"title":"Une meilleure solution","anchor":"a-better-solution","children":[]},{"title":"Une meilleure solution alternative","anchor":"an-alternative-better-solution","children":[]}]},{"title":"Plus que du simple code HTML","anchor":"more-than-just-html","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/5.1/topics/"},{"docname":"topics/class-based-views/index","title":"Vues fondées sur les classes","url":"/fr/5.1/topics/class-based-views/"}],"prev":{"docname":"topics/class-based-views/generic-editing","title":"Gestion de formulaires avec les vues fondées sur les classes","url":"/fr/5.1/topics/class-based-views/generic-editing/"},"next":{"docname":"topics/migrations","title":"Migrations","url":"/fr/5.1/topics/migrations/"},"formats":{"html":"/fr/5.1/topics/class-based-views/mixins/","markdown":"/fr/5.1/topics/class-based-views/mixins.md","json":"/fr/5.1/topics/class-based-views/mixins.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/topics/class-based-views/mixins.txt","official":"https://docs.djangoproject.com/fr/5.1/topics/class-based-views/mixins/","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"]}