Présentation d'un projet Wagtail/Django @gabigab117
Session du 12 décembre 2024 à 21h00
Développement Web & Frameworks
Veille & Discussions
Présentation d'un projet Wagtail/Django @gabigab117
Je propose un talks de 30 min à 1h sur mon projet : https://www.gabrieltrouve.fr/
On regardera la structure d'un projet que l'on commence avec wagtail start, un peu différente à django-admin start.
Et au passage on pourra regarder quelques méthodes de django, et les signaux 🙂
Evidemment on va passer du temps sur Wagtail :
Création du projet
Structure
Création du sitemap en 3 minutes !
Créer facilement un formulaire Wagtail
Mettre en place un système de tags
00:08:25 :Maintenant, je vais montrer la partie sur Django. Je vais montrer le code après, je vous rassure. Je suis connecté sur un projet test.Donc là, en fait, ce que je me suis fait aussi, c'est une partie gestion des factures, gestion des clients, des projets que je fais pour mes clients.
00:10:00 :Je peux les créer aussi ici. Donc, tout bêtement, tac, je crée pour un client, numéro de facture, date d'émission. Je choisis les services.Donc là, si on remarque bien, c'est un formulaire Django, mais je n'ai que les services qui sont à fausse, parce que normalement, quand vous allez voir, j'ai un many-to-many, vous avez tous les services qui s'affichent comme ceux qui sont à flou.
00:10:24 :Mais là, on va voir comment on peut filtrer dans les formulaires Django avec des query sets pour n'avoir que certains éléments de many-to-many.Donc voilà, et ce que je me suis fait qui est plus pratique. Donc là, je crois comme client... Attendez, j'ai entendu que ça sonne. Vous m'arrêtez si jamais vous avez une question.
00:11:16 :Donc voilà. Maintenant, pour la partie code. Est-ce que ça va pour l'instant ou pas ?Oui, super. Oui, ça va super.J'ai vraiment fait un tour basique de ce que ça fait, les fonctionnalités du site en lui-même. Comme ça, vous avez vu un peu le back-office qui ne me sert pas.
00:11:36 :Ça ne me sert pas que de projet de blog, mais en fait, je compte en faire un back-office avec plein de petites utilitaires.Et donc là, on est sur le projet. Donc, j'ai utilisé ici ce qu'on appelle Wagtail. Je ne sais pas si tout le monde connaît.
00:11:53 :Juste, il y en a qui ne connaissent pas, ils peuvent me le dire.J'ai juste regardé quand on avait parlé lors d'un mentorat. Mais voilà, c'est tout. Je n'ai jamais manipulé en fait.
00:12:05 :Je ne connais pas non plus.Ok, ok. Pas de problème. Wagtail, si j'ai un lien là.J'ai fait une présentation avec Thierry à la PyCon à Strasbourg. C'est vrai qu'en France, ce n'est pas hyper connu.
00:12:24 :Comme c'est Thierry, en Suisse, c'est vachement connu. Dans les pays anglo-saxons, c'est hyper connu.Mais en France, on n'est pas encore trop Wagtail. Mais c'est super bien en fait.
00:12:34 :Donc en fait, Wagtail, je vous en ai parlé tout à l'heure.En fait, vous installez ça sur Django. C'est vraiment une librairie pour Django.Donc, vous l'installez en fait avec Django.
00:12:47 :Donc vous pouvez l'installer, avoir un projet Django et l'installer par-dessus Django.Mais ça va demander plus de configuration.Ou, ce qui est très bien, ici il y a un... Je vais vous mettre le...
00:12:59 :Pour ceux qui veulent aller voir le chat, il est où là-dessus déjà ?Hop.Vous avez cette partie-là en fait qui est vachement bien parce qu'elle vous apprend à utiliser de manière basique Wagtail.
00:13:13 :Et en fait, vous pouvez directement partir avec Wagtail sans s'installer.Ceux qui connaissent du coup, j'imagine le Django Admin Start Project.Et en fait, vous avez le Wagtail Start My Site.
00:13:25 :Donc en fait, vous pouvez démarrer un projet directement avec Wagtail.Donc il y a quelques temps, quelques mois, quand j'ai fait une petite présentation là-dessus sur le Discord,je disais que j'avais une préférence de partir en fait sur un projet Django et d'installer Wagtail par-dessus.
00:13:39 :Mais en fait, j'ai carrément changé d'avis.J'ai complètement changé d'avis.Parce qu'en fait, là du coup, c'est un projet que j'ai créé directement avec Wagtail.
00:13:48 :Donc, ce que va apporter Wagtail en fait par rapport au fait de l'installer par-dessus Django,le fait de partir directement avec Wagtail, c'est qu'il y a pas mal de choses qui sont préconfigurées.
00:13:58 :Donc par exemple, je pars ici, dans Project.Et en fait, les settings, pour ceux qui font du Django, ils sont habitués à avoir un fichier de settings .py.
00:14:09 :Là, en fait, c'est déjà séparé en base.Ça, vous avez vos settings de base.Et ensuite, un fichier pour le développement et un fichier pour la production.
00:14:20 :Donc là, si je vais dans le fichier de base, on voit qu'il y a pas mal de choses qui sont déjà installées.Moi, j'en ai installé.
00:14:29 :Mais tout ce qui est Wagtail ici, c'était déjà prêt.Je n'ai rien eu à installer en plus.Parce que je suis parti avec un Wagtail start.
00:14:38 :Et j'ai juste après ajouté, moi, sa partie d'ici.Tac, tac, tac, jusqu'en bas.Donc voilà, vos applications.Ça ressemble beaucoup au style Django, de toute façon.
00:14:50 :Petite différence, c'est que ceux qui sont habitués à ces classes, c'est avec Wagtail.Ils virent ça avec le module OS.Je pense que ça va bientôt changer, parce qu'il n'y a pas de raison d'utiliser encore OS.
00:15:00 :C'est bien, mais je pense que ça se tient par partir à passe libre.Ce qui fait que, du coup, je me suis déjà fait avoir.
00:15:08 :Parce que je gère mes environnements virtuels, moi, avec Environ.Et à chaque fois, avec passe libre, je convertis en chaîne de caractère l'objet passe libre.
00:15:17 :Mais en fait, là, il n'y a pas besoin.Donc, c'est pour ça.Ce qui nous fait du Wagtail, un jour, n'oubliez pas que c'est géré avec OS.
00:15:24 :Et que, du coup, ce n'est pas le même objet que passe libre.Ça évitera les problèmes.Du coup, là, vous avez les middleware.Les middleware, comme vous pouvez en voir avec Django.
00:15:37 :Mais un reste ici avec Wagtail.La constante template, je continue.Tout ce que vous pouvez trouver avec Wagtail.Avec des choses préconfigurées.Ok.Certaines constantes.
00:15:54 :Là, je ne rentre pas dans les détails, parce que j'avais déjà fait une présentation.Peut-être pas sur le suite settings en particulier.Mais je vous laisserai voir la doc.
00:16:02 :On va plus partir après sur la partie Django.Et vraiment les parties, ce qu'on appelle les pages de Wagtail.Que sur le suite settings en lui-même.
00:16:10 :Donc, voilà.Tout est configuré par Wagtail.C'est eux qui fournissent tout ça directement.Et donc, moi, j'ai configuré à partir d'ici.Même si je modifie des choses ici ou là.
00:16:24 :Après, j'en ai rajouté pas mal ici en bas.Donc, j'utilise un modèle utilisateur custom.Ici, je gère mes envois d'email ici.Donc, vous voyez qu'à chaque fois, bien sûr, ce qui est mot de passe, c'est caché.
00:16:39 :Je le cache.J'utilise ici ce qu'on appelle Crispy.Ça, ça va intéresser pour ceux qui font du Django dans tous les cas.Parce que ça permet d'avoir des beaux formulaires.
00:16:51 :Surtout que des formulaires à ne pas s'embêter avec la mise en forme du formulaire.Ça permet d'avoir des formulaires assez classes directs avec ce qu'on appelle Django Crispy Forms.
00:17:01 :Ça, c'est pour toi, Stéphane, qui t'embêtais tout à l'heure.J'ai mis un système de récapture pour l'envoi d'email.Et puis, ça, c'est mes...Comme tu l'as vu tout à l'heure, dans mon parti bloc, tout ce qui est les blocs de code.
00:17:14 :Et puis, voilà.Ça, c'est juste pour...Je regarde si je peux l'enlever.C'était pour les X-Frames dans mon projet.Mais je pense que je ne vais pas l'enlever maintenant.
00:17:23 :Je vais voir.Donc, voilà.Ici, je vais faire mes variables d'environnement.Ici, avec Environ.C'est un petit module très sympa.Vous mettez vos variables d'environnement.
00:17:37 :Vous les mettez dans un fichier.Moi, c'est dans le fond Env qui est là.Et ensuite, ici, j'ai ma classe.Je fais un ReadEnv.Et par exemple, vous voyez qu'avec...
00:17:51 :Vous allez voir que si j'ai la liste des...Je vais mieux la liste des sites.Je ne sais plus.Elle doit être là-haut.Elle est peut-être dans ma fichier.
00:18:02 :Je suis désolé.Dev.Là, c'est Hello World Host.Voilà.Donc, en fait, avec Env, vous pouvez directement...Parce qu'ici, des bugs attendent un booléen.Hello World Host, ça attend une liste.
00:18:17 :Et en fait, ne vous embêtez pas,vous pouvez directement avec Env, ici, le booléen Env,Environ, avec Django Environ,convertir à chaque fois ce que vous avez cherché dans le point Enven liste, en booléen, ainsi de suite.
00:18:29 :Donc, c'est super pratique.Donc, voilà.Un peu pour le côté settings.J'ai bien séparé mes settings.Comment ça se présente maintenant ?Dans le dossier Project, qui est un peu un dossier central,j'ai les templates.
00:18:46 :Comment ça fonctionne ?Ici, j'ai le template de base.Le HTML est vachement gros.De toute façon, on ne va pas faire de HTML ce soir.
00:18:55 :Je vous montre juste rapidement ce que je fais.Donc, j'ai un HTML de base que je vais étendre à toutes les pages de mon site.
00:19:01 :Ça m'évite, par exemple, de remettre tout ce qui estTitle, Meta, le menu.Je ne vais pas l'écrire avant chaque page.Je l'utilise sous forme de composants.
00:19:11 :Enfin, je l'étends, en fait,sous toutes mes pages HTML.Je fais un extend.Un petit truc sympa à voir avec Wagtail,c'est qu'ici, ils vous fournissent un template de base,en plus, avec les informations.
00:19:30 :Ici, en fait, dans la balise Title,ils fournissent déjà tout ce qu'il faut, en fait,pour que ça soit fait de manière dynamique.Et c'est pareil pour la balise Meta, ici.
00:19:42 :La balise Meta, vous voyez, elle est dynamique aussi.Donc, en fait, ici, vous allez retrouver tout ce que vous mettez.Tout ce que vous mettez, par exemple,si je reviens là, dans une page,que je vais dans Promotion,le titre, la métadescription,et bien le titre, il va bien se retrouver ici de manière dynamique,
00:20:02 :et la métadescription aussi, elle va se retrouver ici de manière dynamique.Voilà.Donc, dans mon template de base, il y a aussi ce qu'on appelle un CDN pour HTML.
00:20:11 :Ça, c'est ce que je faisais en recherche dynamique.Donc, on verra après.Et, bon, voilà, après, c'est un menu.J'utilise du Tidewind.Qu'est-ce que je peux vous montrer ?
00:20:20 :Alors, ceux qui font du Langos, ils peuvent être un peu déroutés.J'utilise ce qu'on appelle ici des slugs URL.Je n'utilise pas les URL à la Langos,mais j'utilise ici la balise des slugs URL.
00:20:30 :Donc, c'est pour avoir les slugs de Wagtail.Voilà, puis après, c'est du HTML,qui n'est pas le plus propre du monde, parce que, moi, le HTML,ce n'est pas mon fort, mais bon, voilà.
00:20:43 :Donc, ça, c'est le fichier de base que j'étends.Tac, on est dans l'ossier projet.On a vu les settings, et ça, c'est mon fichier d'URL.
00:20:53 :Il faut savoir que quand vous vous démarrez avec un projet Wagtail,en fait, vous avez déjà la moitié qui est configurée.Il y a déjà la moitié qui est préconfigurée.
00:21:02 :Moi, j'ai juste rajouté quelques...Par exemple, c'est Customer, Admin.Ça, c'est moi qui l'ai rajouté.Le sitemap, moi aussi.D'ailleurs, on verra que c'est vachement facilede faire un sitemap avec Wagtail.
00:21:17 :Et puis, voilà, ça tourne assez vite.Wagtail, il est très vite prêt à l'emploi,votre projet avec Wagtail.Et donc, maintenant, on va partir plus sur des modèles.
00:21:27 :Alors, comment je vais faire ça, du coup,avant de partir sur le compte ?Par exemple, la partie blog.Déjà, j'ai une partie qu'on appelle Core.
00:21:39 :Une partie Core, OK.C'est un peu une application centrale vers la page légale.Et en fait, je m'en sers ici pour avoir icice qu'on appelle un modèle de page Wagtail.
00:21:56 :Bon, là, je commence un peu plus...Enfin, un peu pas hard, mais je commence fortparce qu'en fait, ici, j'utilise ce qu'on appelleune classe abstraite.
00:22:06 :Avec Django, ça existe.Peut-être pas tous faites des classes abstraitespour l'instant.Des modèles abstraits, mais ça existe avec Django.Donc, c'est un modèle qui ne va pas être enregistréen base de données, mais qui va vous servir d'interface.
00:22:22 :Vous retrouvez un peu la même chose en Python.Pour ceux qui ont déjà fait du ABC,vous allez pouvoir vous créer des classesque vous n'allez pas pouvoir instancierqui vont vous servir de base d'interface, en fait.
00:22:38 :Donc, là, c'est pas pareil, mais sur le principe,c'est vraiment une classe qu'on ne crée pasen base de données, mais qui va vous permettred'avoir, en fait, une interface.
00:22:48 :Donc, ici, pourquoi j'ai fait ça ?Donc, j'hérite de l'objet page de Wagtail,mais il faut savoir que l'objet page de Wagtail,il hérite lui-même, quant au nom de l'héritage,de Models, de Django, pour ceux qui connaissent,de Models.models.
00:23:02 :Donc, ça, clairement, ici, j'ai créé ce qu'on appelleune légale page, en dessous, qui hérite de GenericPage.Et donc, ça, celle-là va être créée en base de données.
00:23:10 :Ce modèle-là va être créé en base.Pourquoi j'ai créé une page générique, ici,un modèle abstrait ?Parce qu'en fait, sur toutes mes pages,je sais que je vais avoir un header, ici,et donc, je ne voulais pas, à chaque fois,me retaper à l'écrire.
00:23:25 :Bon, c'est un peu saignant, j'avoue,mais je le raterais mieux que de le réécrire,mais là, je voulais en hériter.Comme ça, à chaque fois, je n'ai pas à le redéfinir.
00:23:32 :Donc, voilà.Et puis, ici, mon premier modèle de page Wagtailqui va être créé en base de données,c'est la page légale.Alors, comment ça fonctionne ?
00:23:47 :Ici, donc, j'hérite bien de page,j'ai, du coup, mon header qui est là,et en plus, j'ai un body.Et ça, le content panel, en fait,c'est ce qui va être rendudans l'administration de Wagtail.
00:23:59 :Le content panel, bah, voilà.Donc, par exemple, là, on était sur la page légale.Donc, si je reviens,donc là, j'ai déjà une page légale qui est créée,voilà, elle est là.
00:24:11 :On a dit, j'ai le header,et ici, je le rends dans le panel.J'ai bien le header et le body,et si je reviens là,j'ai bien le header et le body, voilà.
00:24:25 :Donc, tout simplement, en fait,c'est rien de très compliqué.Ce que je voulais vous dire,c'est que, du coup,quand vous allez créer un modèle ici,il va vous falloir un template qui correspond.
00:24:37 :Donc, si ça s'appelle légale page,eh bien, vous allez l'appeler légale page,et là, avec le cam et le case,il va falloir penser à l'underscore, OK ?
00:24:45 :Il faut bien suivre ce schéma-là.Cette fois-quelle va automatiquement reconnaître,du coup, que ce modèle de page icidoit être utilisé avec ce template-là.Donc, ce que je disais,c'est que, du coup, ici,j'ai créé un modèle légale page.
00:25:02 :Donc, clairement,si j'avais envie de recréer une page légale,un modèle basé sur ce modèle-là,eh bien, je peux, par exemple,c'est celui-ci, hop.Bon, là, j'ai pas d'intérêt,mais je pourrais bien aller voir sur ma légale page.
00:25:17 :Et boum, voilà, j'adore le body.Et en fait, j'ai plusieurs modèles de pages.Donc, vous pouvez très bien en créer,peut-être en faire moins que moi,mais que vous allez utiliserà des endroits différents de votre site.
00:25:29 :Moi, j'en ai créé plusieurs volontairement,parce que j'ai des besoins différents,et puis, ça dépend comment je vais les faire évoluer.Donc, vous pouvez très bien créer, je ne sais pas,une blog index page.
00:25:38 :En fait, c'est que des modèles de pages,donc vous pouvez très bien avoir des noms plus génériquessur vos modèles de pageset les utiliser à des endroits différents de votre site.
00:25:46 :Donc, j'étais là.Et donc, là, c'est un peu la partie centraleoù j'ai mon générique page qui est abstrait.Et donc, pour après,avec Wagtail, il n'y a pas de vue en soi.
00:25:59 :Je n'ai aucune vue ici.Si je pars dans la partie blog,aucune vue, OK ?Et donc, là, c'est parti.Il y a beaucoup plus de choses.
00:26:10 :Sans trop rentrer dans le détail,on va plus après regarder un peucomment fonctionne Wagtail,et puis après, on ira sur Django.Il y a des petites choses sympas à voir sur Django.
00:26:22 :Du coup, la partie blog.Donc, j'ai créé un modèle blog index page.En gros, ça va me permettre d'avoir une page d'indexoù je vais afficher un peutous les articles qui vont apparaître dessusavec des petites cartes,comme on l'a vu ici.
00:26:40 :Donc là, moi, j'utilise ma blog index pagejuste pour cette page.Donc, vous allez me dire,c'est peut-être dommage d'utiliser juste un modèlepour juste une page,mais ça ne me dérange pas trop.
00:26:50 :C'est un projet perso, en plus.Je vais faire un peu comme je voulais,et puis je préfère avoir un modèle exprèspour cette page-là,si je veux la faire évoluer par la suite.
00:27:01 :Donc, j'ai mon modèle qui gérit bienle générique page.Et là, j'avais besoin que d'un header,donc je n'ai pas des signes d'autres attributs.Donc, je vais envoyer le headerdans le panneau ici, dans le panel.
00:27:13 :Et vous allez voir,j'ai rechargé le contexte.Et ici, blog page,ça va être justement chaque articleque j'ai utilisé le modèle blog pagequand je le rentrais là.
00:27:28 :Et le blog page, du coup,il a une image principale.Alors, est-ce que je l'ai importé ?Images, ici, c'est bien.J'utilise le modèle images de Wagtailqui est intégré à Wagtail.
00:27:41 :Ils ont leur modèle d'images intégré.On a vu tout à l'heure qu'il y avait une galère d'images.Donc, ils ont leur propre modèle de documents et d'images.
00:27:47 :Donc, pour le lier,je l'importe ici en foreign key.J'ai un date field.Et ici, j'ai ce qu'on appelle un stream field.Pour le body, on va revenir après.
00:27:58 :J'ai la gestion de mes tags.Et en fait, ce que vous pouvez faire aussi avec Wagtail,c'est qu'il y a l'attribut search fields.Et en fait, search fields,ça permet d'indexer les champs que vous voulezdans un moteur de recherche central à Wagtail.
00:28:13 :Donc, moi, si je viens ici, j'ai un moteur de recherche.Et en fait, ça va aller rechercher dans tout ce que j'ai indexéavec search fields ici.
00:28:23 :Voilà.Et pour le fun, je vais vous montrer, du coup,sur un modèle ici, par exemple.Donc, je disais, du coup...C'était où ?Le stream field, en fait, ça va vous permettre de faire un...
00:28:41 :de vous personnaliser un peu pour vos publications.Donc là, pour écrire mes paragraphes,j'utilise un recess block.J'insère des...Je peux insérer aussi des blocs de code.
00:28:52 :Mais vous pouvez aussi, je ne sais pas,ajouter un autre...autre chose, un autre block.Je ne sais pas, un image block, par exemple.Et en fait, c'est ce que je disais.
00:29:02 :C'est ici, dans le body.J'insère des paragraphes.J'envoie des blocs de code.Mais je peux très bien choisir un paragraphepour écrire un autre bloc de code.
00:29:08 :Ainsi de suite.OK.Paragraphes, code.Moi, j'en ai deux.J'ai paragraphes et code.Donc, voilà pour le stream field.Et vous pouvez créer vos...Comme ça, des blocs d'éléments, en fait,où à chaque fois, bah là, tiens, j'ai envie d'utiliser,je ne sais pas, une URL.
00:29:21 :Bah, boum, j'utilise une URL.Je me suis prévu un URL block.Ainsi de suite.Donc, voilà.Ça, c'est mes tags.Je vous montrerai rapidement après comment je les gère.
00:29:30 :Ça part un peu flou comme ça, j'imagine.Et dans mon administration, pour que ce soit plus clair,j'utilise ce qu'on appelle des multi-field panels.Donc, il faut très bien avoir des panelsavec tous vos attributs, ainsi de suite,genre header, body, comme ça, à la suite.
00:29:46 :Mais il est possible de les regrouper.Par exemple, j'utilise ce qu'on appelle,dans mon panel, comme on a vu tout à l'heure.Mais ici, j'ai un multi-field panel,ce qui veut dire que je peux regrouper mon header,qui est dans l'héritage de GenericPage,l'attribut date, l'attribut mainImage,images qui sont mainImage, date, header.
00:30:12 :Je peux les regrouper ensembleet j'appelle mon groupe, ici, en tête.Et ensuite, je n'ai pas créé de groupe,mais j'ai mis comme ça le body et le tag.
00:30:20 :Ce qui veut dire qu'ici, c'est bien en tête.Vous voyez, j'ai bien le header, la date, l'image principale.Ils sont regroupés ensemble, en fait.Comme ça, j'ai mes infos, j'écris ce que je veux,je le cache et j'écris.
00:30:33 :Là, c'est vraiment pour l'organisation, on va dire.Ça me permet d'organiser tous mes attributsun peu comme je veux.Donc voilà, et très important,vous voyez qu'avec Wagtail,vous pouvez publier ou enregistrer sans publier.
00:30:50 :Alors, il faut faire attention,parce que si vous envoyez tout ici dans le contexte,je suis allé chercher dans le blog index page,je suis allé chercher toutes mes instances de blog page,mes articles de blog,sauf que, attention,je les envoie dans le contexte,mes blog pages,sauf qu'il faut bien penser à utiliser ici
00:31:13 :la méthode live.Parce que si vous ne le faites pas,même tout ce que vous faites,que vous faites juste enregistrer,même si ce n'est pas publié,ça va quand même apparaître.
00:31:25 :Donc Wagtail, le point live,ici, va vous permettre d'afficherque ce qui est en publié.À ne pas oublier, parce que je croisque dans le tout de Wagtail,il y a un moment où ils surchargentune méthode comme ça de contexte.
00:31:39 :Et je crois qu'ils mettent juste un contexteoù je ne sais plus s'il bloque page ou autre chose,mais il prend un blog page pour un object,point order, mais ils ne mettent pas le point live.
00:31:47 :Ce n'est pas très grave,mais il ne faut pas se faire avoir,et il faut penser que si vous ne le mettez pas,tout ce qui est en brouillon, ça apparaît aussi.
00:31:55 :Donc voilà, ici, le contexte qui est là,sur la blog avec page,c'est tous les articlesqui sont ici publiés.Par exemple, voilà.Donc voilà, en gros,pour le blog et le système de tags.
00:32:11 :Je vais en parler maintenant,que vous voyez tout en bas, par exemple,quand vous cliquez,qui est ici, donc c'est l'article sur Wagtail,où je n'en ai qu'un.
00:32:21 :Le système de tags, j'ai crééune application à part pour gérer mes tags,qui est là.J'ai un modèle,et en fait,j'utilise des objets de Wagtail.
00:32:33 :Pour ceux qui ne font pas encore de Wagtail,il y a quand même pas mal de petites choses à apprendre.Pour ceux qui commencent avec Django,je peux vous lancer dessus,mais ça demande quand même un petit peu d'apprentissage,donc c'est vrai quevous pouvez le faire à l'aidé en même temps,
00:32:49 :mais moi, je trouve que c'est biende connaître bien Django à la base.Et donc, je disais,ici, j'utilise ce qu'on appellema classe, qui hérite detagItemBase, et en fait,j'utilise en ParentalKey.
00:33:03 :Alors ça, ParentalKey, c'est encoreun concept qui estpropre à Wagtail.Avec Django, vous avezles one-to-one, ainsi de suite,les many-to-many, mais vous avez aussi la foreign key.
00:33:15 :Avec Wagtail,ici, on a ce qu'on appelle une ParentalKey,et en fait, l'objetParentalKey hérite deforeign key.Sauf qu'ici,on est dans une relationvraiment de parentà enfant, donc ça veut dire quetoutes lesinstances de tag,elles vont vraiment être, entre guillemets,les enfants d'une page de blog.
00:33:41 :Je m'explique.Je m'explique, je suis sur un article.Je peux les modifier directementd'ici.Quand vous avez une...Pour ceux qui sont au début avec Django,vous ne pouvez pas encore bien visualiser, maisquand vous avez...
00:33:59 :Vous voulez ajouter, par exemple,dans un modèle, vous créez une instanced'un modèle.Quand vous avez ici,vous avez votre foreign key,il faut déjà qu'elle soit créée.
00:34:11 :En fait,ce qui est bien avec Wagtail,c'est qu'il n'y a pas besoin qu'elle soit déjà créée,c'est que vous pouvez ici les créer à la volée.
00:34:19 :Avec Django, il faut d'abordaller créernotre...Quand on a des éléments liés par foreign key, créer notreélément, et après, on peut le sélectionnerpour allercréer notre instance.
00:34:33 :Vous pouvez tout à la volée et tout créer en même temps.Tout ce qui estl'article de blog,et tout ce qui est ici, en blogtype page,tout va se créer en même temps. Il n'y a pas besoin de les créer avant.
00:34:45 :C'est ça que je veux dire.On va le voir après avec un formulaire.Et ici,c'est mon modèle de page.Il y a un villa et un port local.
00:34:55 :Ça ne me dérange pas trop trop, j'en ai qu'un, maisc'est pour éviter d'avoir un problèmed'import circulaire.Du coup,excusez-moi, ici,pour pouvoirutiliser mes tags,j'ai crééun...
00:35:15 :comment dire...un modèle page.Ici, tout simplement,je surcharge ici le contexteet en fait, j'utilise...je fais un filtresur les pagesde mon blog. Ici, j'ai tags.
00:35:31 :Ici, j'ai tags.Etje vais les filtrersur le texte sur lequelil va cliquer. Et ici,j'utilise le point live, surtout.Et ça me permet, du coup, quand je cliquesur...
00:35:47 :sur le tag,par exemple,si je clique sur le tag,j'atterris bien sur une pagespécifique.Et donc, j'ai toujours, comme tous mes autres modèles,j'ai bien ici un modèlequi s'appelle blog. Un modèle de page.
00:36:03 :Blog, tag, index, page.Et il est ici.Blog, tag, index, page.Euh...Donc voilà.Et est-ce quepour l'instant ça va, ou je vais trop vite,ou pas ? Dites-moi.
00:36:21 :Non, non, vas-y.Je suis, je suis.Ok, je voulais un petit pouce levé.Ok. Ouais, je sais, je pars un peudans les trucsque je te présente en gros, mais il y a pas mal de choses.
00:36:35 :En plus, une présentation,j'ai déjà présenté des choses très similaires il n'y a pas longtemps.Bon, en gros, donc voilà pour Wagtail.Il faut savoir que quand vous faites un...
00:36:45 :un...quand vous initialisezun projet avecWagtail, vous avez déjà ici, par exemple,cette application là, Home.Celle-ci sert, ce qui est très pratique, parce qu'en faitvous avez déjàvotre, entre guillemets,votre vue pour le moteur de recherche qui est déjà prête.
00:37:03 :Et c'est trop bien. Vous n'avez rien à faire, elle est déjà prête.Donc voilà.Vous avez juste à indexer vos modèles,et puis après vous réutilisez ça.
00:37:11 :Et c'est parti.Euh...Qu'est-ce que je voulais dire ?Voilà, en gros, là on a fait un petit tour de Wagtail.Je vais arrêter Wagtail parce queça fait pas mal de choses.
00:37:23 :Mais donc, je ne l'ai pas montré tout à l'heure, mais évidemment,pour mes modèles, un blog andan ex-page, blog page,j'ai des templates qui correspondent à un blog, un ex-page, blog page,ainsi de suite.
00:37:33 :Maintenant, on vaattaquer sur la partie bianco.Je vais...C'est plus celle qui m'intéressait à montrer ce soir.Sachant que je vous ai parlépas mal de Wagtail il y aquelques temps sur le Discord.
00:37:47 :Ça fait quand même plus d'une demi-heure que j'en parle.Euh...Donc...Pour la partieDjango,on va commencer par le côté...le côté interface.Euh...
00:38:03 :Oui, juste, dernière chose.Le côté contact, ici.Je ne vais pasen parler ce soir parce que j'ai...On a dû pas mettre de choses sur Wagtail.
00:38:13 :On va partir sur Django.Mais pour tout ce qui estformulaires de contacts, par exemple,j'utilise ce qu'on appelleles...les formulaires Wagtail, ici.Voilà à quoi ça ressemble.
00:38:27 :Ça me permet de construire des formulairesde manière dynamique.Je vous montre juste la forme.Dans mon interface...Dans mon interface ici,si j'ai envie d'aller créerun formulaire,hop,je mets le nom et je peux rajouterautant de choses que je veux, hop,l'étiquette, le texte, qu'est-ce que c'est,
00:38:49 :et bien je pars un e-mail, texte multiline,et ainsi de suite, boum.Et hop, je rajoute autant de choses que je veux,ainsi de suite, ainsi de suite, ainsi de suite.
00:38:57 :Et donc, voilà, hop,je peux m'échanger les places,et échanger les places des chosescomme je veux, et puis ainsi de suite.Et donc, juste pour info,ici, j'ai ce qu'on appelleun form field en parental key,comme je disais tout à l'heure.
00:39:13 :Donc le RelatedName,ici, c'est FormField, doncje l'utilise dans mon...dans maclasse de formulaire, ici, le FormPage,et donc la ParentalKey faitque je peux créer mes instancesde fields, en fait, de champs,en même temps que je crée le formulaire lui-même.
00:39:31 :Voilà. C'est juste ça sur lequelje voulais revenir.Et vous n'embêtez plus avec Wagtail.Et donc Wagtail,Django, la partie vraiment Django.Pour info, ici,j'ai fait du Tailwindpour l'interface.
00:39:47 :Je vais parler un peu des extensions que j'utilise,peut-être avant. Donc, en gros,j'utilise ici...Donc là, j'ai une application Themeque j'ai créée avec ce qu'on appelle Django Tailwind.
00:39:57 :Et en fait, je...Hop.Alors, attendez, c'est où ? Tac.Et ici, par exemple, je vais aller installeren plus, quand j'ai besoin,j'ai installé, je crois, dessus...
00:40:11 :J'ai installé Daisy UI,qui est une extension de Tailwind.Et donc, en fait,ça, cette partie Theme, je l'ai géréeavec ce qu'on appelle, du coup,Django Tailwind.
00:40:25 :Et Thibault avait écrit un articleque j'ai mis à jour en 2023,c'est ça, mais qu'il a écrit en 2021,mais qui est encore valable, il n'y a pas de problème.
00:40:33 :Je vous laisserai aller le voir et il explique toutcomment installer Django Tailwindsur Django.Et c'est vraiment très simple.Et il y a juste à suivre, en fait,tout le petit tuto.
00:40:45 :Donc,j'utilise Django Tailwind, moi, pourle côté CSS.Qu'est-ce que j'allais dire ? Tailwind ?Et oui, donc, ensuite,pour la partie...pour que mes formulaires, en fait,soient propres, si je vais, par exemple,sur mon site...
00:41:05 :Voilà, en fait, là, ici, pour qu'ils soientbien en form,j'ai utilisé ce qu'on appelleDjangoClippy Forms.Alors, ça, ceux qui débutentavec Django,vous pouvez l'utiliser direct, il n'y a aucune difficulté à l'utiliser.
00:41:21 :C'est super pratique, ça s'installefacilement.Et, en fait, ça vous permet, après,d'utiliser vos formulaires, donc, par exemple,si je reviens sur le...Mon form, il est où ? Contact,
00:41:33 :Template,hop, j'utilise, ici,juste un structure Clippy,pour utiliser Clippy Forms,ou vous pouvez utiliser différent, aussi,utiliser, ici, directement Clippy,et ça, je le fais quand j'utiliseClippy différemment, je ne vais pas en parler en détail,mais, en gros, j'utilise Django Clippy Formspour rendre mes formulaires de manière très, très propre,
00:41:53 :sans écrire, quasiment, une seule lignede CSS.Donc, j'utilise Django Clippy Forms, et, en plus,j'installe,donc, pensez à tout, Crispy Tailwind.Hop, et, je vous expliquecomment on installe, bah, Crispy Tailwind,et ça vous permet de mettre en forme, avec Tailwind,avec Exact Tailwind, vos formulaires.
00:42:11 :Voilà, avec le petitfiltre Crispy, comme je l'ai montrétout à l'heure.Sachant qu'ils ont prévu, avec,la version Bootstrap 4, la versionBootstrap 5,Bulma, aussi, donc,c'est compatible avec pas mal de choses, et çapermet de vous éviter, de trop vous embêter,à mettre en forme vos
00:42:31 :vos formulaires. Vous pouvez le personnaliser à fond,ça, en fait, avec Crispy Forms.Donc, voilà, pour la partieextension que j'utilise,j'ai quoi, ici, Project,Settings,non, pas, Base,alors, j'ai quoi, extension JTailwind,Wagtail CodeBlock, ça, c'est pour mes codes,DjangoRecaptcha,pour avoir mes sécurités Google,Wagtail Recaptcha pour la partie Wagtail,
00:42:57 :OK,c'est tout.J'utilise Django,voilà, Django Cleanup, aussi.Django Cleanup,très pratique,parce que quand vous,si vous avez un modèleoù vous chargez des images ou des fichiers,donc, vous chargez,avec votre modèle, vous créez une instance, vous chargez l'image,supprimez l'instancede votre, je ne sais pas,
00:43:23 :par exemple, j'ai un système de facture,moi, dans mon site,donc, si je crée une facture,que j'uploade une facture,que je supprime l'instance de la facture,le fichier médias lui-même, c'est le PDF,il va rester dans mes dossiers,sauf que moi, quand je fais ça, je tout supprime,
00:43:39 :et, en fait, j'ai Django Cleanup qui permetde faire en sorte que quand vous supprimez une instancede facture,ça a supprimé le fichier médias qui est lié, en fait,ça supprime tout, voilà, ça me permet d'être plus propre.
00:43:49 :Donc, voilà,pour les extensions.Maintenant,pour la partie gestion des comptes.J'utilise,comme toujours, moi, je suis sur ça,je n'utilise pas le modèle utilisateur de Djangoqui estde base, je vais l'étendre,je vais l'utiliser, en fait, je vais en hériter,et après,je vais le modifier,et je vais me faire un petit custom manager.
00:44:17 :Ça, Thibaut, pour ceux qui sont du Django,il en parle dans la formation,il va vous le faire faire.Donc, je redéfinisles méthodes pour créer l'utilisateuret créer le super utilisateur, en gros, ici.
00:44:31 :Donc, j'ai un manager custom.Donc, ça me permet, en fait,juste pour la théorie,si vous avez une applicationDjango,j'utilisaisle modèle utilisateur de base de Django,et que d'un seul coup, vous vous dites,ah, j'aimerais bien, je ne sais pas,modifier mon modèle utilisateuret rajouter des champs.
00:44:53 :Je vous le dis,ça va être chiant. Ça va être très compliqué.Donc, il vaut mieux partir sur un custom userqui n'est pas très différent.
00:45:01 :J'ai très peu surchargé.Mais comme ça, si vous avez besoin,après, vous pouvez rajouter des attributs facilement,sans que ce soit problématique de changerde modèle utilisateur en cours de route.
00:45:11 :Donc, voilà. Il n'y a aucune vueparce que je ne permets pas de se connectercomme ça sur mon site. C'est juste pour moi.Donc, il n'y a que moi, l'utilisateur.
00:45:21 :Mais je me suis dit, je préfère prévoir le coup,avoir mon modèle utilisateur custom,et au moins, si je veux un jour faire plus de chosesavec mon site, ça marchera.
00:45:29 :Très important,l'administration.J'ai fait un mentorat Django.J'en ai parlé il n'y a pas longtemps.Donc, toujours, quand vous avez un modèle utilisateurici,toujours, quand vous le rendezdans l'administration, quand vous faites un admin,un principal registreur,créez-vous des classes qui utilisent l'objetuser-admin, héritées de cette classe-là.
00:45:55 :C'est indispensableparce que le problème, c'est que dans l'administration,sinon, votre utilisateur, il va êtremal rendu, et en plus,vous n'aurez pas les formulaires de changementde mot de passe dans l'administration.
00:46:07 :Et si vous changez le mot de passe dans l'administrationtelle qu'elle, avec,juste en faisant admin, principal registreur, custom user,et bien, vous avez le mot de passe qui va êtreenregistré après en clair dans la base de données,ce qui n'est pas bon du tout.
00:46:19 :Et ça pose des problèmes.Donc, vraiment,en plus, si je ne dis pas de conneries,parce que j'ai vu pas mal de mondequi faisait l'erreur,j'ai créé un article assezcomplet là-dessus.
00:46:35 :Utilisez toujours l'objet user-adminquand vous rendez en administrationvotre modèle utilisateur.Voilà.Donc, voilà.Pour ça,pour la partie compte utilisateur.Et donc, maintenant,on a vu la partie moitié de la partie compte utilisateur,on va voir la partiegestion de tout ce qui estle système de facturation que je vous ai montré tout à l'heure.
00:46:59 :Par exemple,si je pars surles modèles,si je pars sur les modèles,donc,j'ai un client.En fait, dans l'application, je peux enregistrer des clients,des personnes pour qui je vaisbosser. Donc, elles ont un nom,
00:47:19 :un numéro de ciré, une adresse,je mets leur business code, la ville où ils sont.Et là, je metsquand est-ce que je vais créer le compte,entre guillemets.
00:47:29 :C'est pas forcément important, mais j'ai mis quand même.Sachantque cet attribut-là, il se met à jour automatiquementdès que je crée unclient, puisquej'ai rajouté ici un auto-add-through,qui fait que sur un deadfield,en fait, quand vous allez enregistrer votre instance enbase de données, ça se met à jour
00:47:47 :tout seul. En fait, vous n'allez même pas avoirvotre champ, votredeadfield ici, il n'apparaît même pas, c'est juste quedans la base, il sera enregistré, mais vous ne le verrez pasdans l'interface.
00:47:57 :Vous ne pourrez pas y toucher.J'ai une propriété, du coup,pour les clients,qui me permet d'aller voir, en fait, sitoutes les factures, entre guillemets, sont payées ou pas.
00:48:11 :Ça, est-ce que j'en parleaujourd'hui ou pas ?Il ne faut pas vous perdre là-dedans,c'est pas la priorité.Donc voilà, j'ai une méthode d'une propriétéici. Ensuite,
00:48:27 :pour chaque client, je vais avoirdes projets.J'ai bien les clients qui sont liés enMK. Le projet,il a un nom, il a untaux horaire,et je mets une description.
00:48:41 :Etles méthodes, je les verrai plus tardparce que du coup, je peux tout voir. Donc, j'ai les projetset dans les projets, on peut avoir des services.
00:48:49 :Donc, ça veut dire que dans chaque projet,comme je l'ai montré tout à l'heure, on peut créer, on peut dire« j'ai bossé sur ce projet-là pendantune heure tel jour ».
00:48:57 :Donc là, je peux dire « ces jours-là ».Donc, je crée une instancede service qui est reliée à un projet.Je dis « tel jour, j'ai bossétant de temps ».
00:49:07 :Je peux dire si c'est facturéou non. Je pose une description.Et ici, j'ai le total dule total dule total du service, en gros,de combien, entre guillemets, il est facturé.
00:49:19 :Alors,donc là, on a vu, ah, le dernier modèle,Invoice. Donc ça, c'est la facture en elle-même.Elle va être reliée à un client.J'ai un numéro, la date d'émission,de livraison, d'échéance,tous les services qui vont être dans la facture,si elle est payée ou pas, le total
00:49:39 :de la facture, et monfichier PDF. C'est là que je disais tout à l'heurepour le Django Cleanupque quand on supprime une instance deInvoice, ça va supprimer aussi le PDF en lui-même.
00:49:49 :Voilà.Du coup, qu'est-ce que j'allais dire ?Pour ne paspour partir directement, peut-être,je pense sur le total. OK.Du coup, pourun service, ici,qui relie un projet, pour avoirle total, j'utilise la méthodeSave. Et en fait,
00:50:15 :quand je fais un Save.Total, ici,donc c'est bien le total ici, au momentde sauvegarder en base de données,je vais faire le temps que j'ai passé,que je vais multiplierpar le taux horaire du projet.
00:50:27 :Self.Project.AllIrate.OK. Donc c'est bienSelf.Service.Project.ModelProject.AllIrate. OK.Donc là, en fait,c'est un projet où je traverse pas mal les relationsentre modèles.C'est là que c'est intéressant.
00:50:45 :Parce que,c'est pareil pour lafacture. Vous allez voir comment on faitpour mettre à jour le total.Donc ça,je ne vais pas en parler aujourd'hui. Ce n'est pas forcément la priorité.
00:50:57 :C'est pas maintenant.Vous pouvez aussi, directement, dans vos modèles,utiliser une méthode Clean,qui fait, par exemple, que si j'aiune DueDate qui est inférieureà la IssueDate, donc la dated'émission, la date d'échéance qui est inférieureà la date d'émission, je lèveune erreur.
00:51:17 :Et donc,pourle total, en fait,d'une facture, ce que je vais faire,c'est que j'utilise une méthode,ici. Alors,est-ce que je l'utilise ?
00:51:33 :Tac. Là, c'est bon.J'ai une méthode qui est, en fait,mon total.J'utilise, donc,le Self.Total.Je fais un Self.Services.Donc c'est tous les services qui vont être dans la facture.
00:51:47 :Tous les services qui sont làdans la facture.Et là,j'utilise ce qu'on appelle une agrégation.Avec Django, en fait, quand vous faites unAggregate,en gros,c'est que tous les services que j'ai ici,je vais aller chercherla sommede tous lestotaux de mes instancesde services qui sont
00:52:15 :reliés ici, donctous mes services qui sont là dans ma facture.Je vais aller chercher tous les totauxde mes services, OK,qui sont là.
00:52:27 :Et en fait, si vous oubliez cette partie-là,on n'y pense pas pour l'instant.Donc si je fais ça pour l'instant ici,mince, je ne sais pas ce que je voulais faire,tac, je voulais sélectionner ça,ah mince, je n'y arrive pas.
00:52:39 :Hop là. Voilà.Ici, si vous faites ça,ça va vous renvoyer un dictionnaireavec, en gros,ici, la clé totale,enfin, ça va être la clé totale,et vous allez avoir ensuite,en valeur, en gros,la somme ici.
00:52:57 :Et si je, du coup, vu que ça va me prendre un dictionnaire,si je cherchais la clé totale,et bien, j'ai cherché du coupla somme, en fait, de tousmes services cumulés. Voilà.
00:53:07 :Et donc, ça me permet, en fait, de mettrecomme ça à jour le total automatiquementde mes factures en fonctiondes services qui sont dedans.
00:53:15 :Est-ce que ça va pour l'instant ou c'est un peu compliqué ?Dites-moi.Non, non, ça suit, j'accroche,j'essaye.Ok.Ok.Pour les autres, j'espère,ceux qui foncent avec Django, j'espère que c'est pas trop la galère.
00:53:33 :Mais,au moins, vous saurez que ça existe.Sauf que, du coup,pour faire tout ça,et bien, j'utilise ce qu'on appelledes signaux.Et là, en fait, en gros, les signaux,même moi, je mets des upstream pour,quand je reviens dessus,me rappeler de ce que j'ai fait.
00:53:53 :En fait, les signaux, ici,donc ici,ça, c'est...Là, en fait, c'est quand j'utilise unerelationmany-to-many. Donc, en gros,quand je vaisajouter unservice à une facture,quand je vaisenleverun service, une facture,quand je vais supprimer tous les services, une facture,et bien, en fait, ce que je vais faire,
00:54:23 :c'est que ça va mettre automatiquement,du coup,le total de la facture à jour.Ok. Donc, en fait, je passe pour çapar des...des signaux.
00:54:35 :Donc, là, j'ai pas utilisé le plus simple.Celui-là est un peu plus complexe que les autres.C'est une relationmany-to-many. C'est une modification.Donc, dans Invoice,qui est ici,et dans les services,quand j'ai fait une modification,tous les services qui sont associés...
00:54:53 :Donc, là,quand vous faites un signal comme ça,vous pouvez dire post-add. C'est quand vous avezajouté quelque chose dans votre relation many-to-many.Donc, vous avez ajouté un service.
00:55:03 :Donc, par exemple,pour que ce soit plus clair,je vais faire le test ici.Enfin, je vais vous montrer en même temps.Un run-server.Tac.
00:55:15 :Euh...Putain, la vache, c'est la dernière foisque je parle. Donc, là, je suis biensur la partie locale.Donc, facture.Si je fais une facture, vous voyez,là, j'ai les services.
00:55:29 :J'ai tous les services qui sont actuellement créés.Donc, quand j'ajoute un post-add,c'est qu'une fois que j'ai ajouté les services,je peux le baisser.Unpost-remove, c'est après que j'ai supprimé.
00:55:41 :Et un pré-clair, c'est justeavant de faire un clear, de supprimer tous les servicesd'une facture.Et à chaque fois, par exemple, si j'ajoute un service,les services ajoutés,je vais le passer enstatut facturé. Si je le supprime,
00:55:55 :comme ça, il est automatiquement passé en statut.Il n'est pas facturé.Et si je supprime tous les services,je fais un clear de mon modèle au niveaudes services, je les passetous à pas facturé.
00:56:07 :Ici, on pourrait faireun post-clair. Donc, c'est après avoir fait leclair. Moi, je fais un pré-clairparce que si vous faites un post-clair, vous ne pouvez pasrécupérer vos services puisqu'ils sont déjà supprimés.
00:56:17 :Donc, je ne pourrais pas faire instance.Instance, ça va être l'instance de mon invoice.Je ne pourrais pas faire uninstance.service pour l'update puisquej'ai déjà plus de services. Donc, je le fais
00:56:27 :avant qu'il soit supprimé.Automatiquement, quand je fais un save de mon invoice,ça va tous les passer àfalse. Et puis après, ça les retire.
00:56:35 :Donc là, c'est des chosesquand même déjà bien plus complexesavec Django que ce qu'on peut voir habituellement.Mais même ceux quicommencent, comme ça, vous pourrez voir que çaexiste. J'ai
00:56:47 :deux autres signaux. Ici,si je supprime...Donc là, celui-là est beaucoup plussimple. Donc, on voit, ça c'est celuiqui envoie le signal, le sender.
00:56:57 :C'est la facture,le modèle facture. Et quand,juste avant qu'il se supprimede la base, qu'est-ce que je fais ?Juste avant que la facture soit suppriméede la base, au moment où je clique sursupprimer, il y a ce signal-làqu'en fait Django va utiliser.
00:57:13 :Tous les servicesde ma facture, donc les servicesde l'invoice, donc instance,on travaille sur instance, .services.all,il va tous les passer à false.
00:57:25 :Comme ça, ils pourront être utilisésdans l'autre facture.Si j'ouvre une facture, je fais une erreur, je la supprime.Ici, pareil, si je sauvegardeun service,j'ai besoin qu'en faitça aille memettre à jour lafacturedans laquelleest le service.
00:57:49 :Puisque dans ma...Ici, j'ai des services,je vais modifier un service dans la baseil faut que la facture aille se mettre à jouret donc je vais récupérer la facturequi est associée à mon serviceet puis je vais aller faire un update totalde ma facture.
00:58:05 :Donc vous voyez, je crée en fait des méthodesque je réutilise en fait dans mes signauxet comme ça en fait j'aiplus de doctrine que de code à la limite.
00:58:13 :J'ai pas des grossesfonctions en soi, mais voilà.Doncvoilà comment on peut utiliser des signauxavec Djangoet comment on peut réutiliser les méthodes qu'on utiliseen fait dans nos modèles, dans nos signaux.
00:58:27 :Voilà pour cette partie-là, je vais pas prendre trop de tempsaprès, je peux passer rapidement sur les vues.Mais ça a été ou pas déjà là ?
00:58:37 :Ou j'ai trop perdu ?A moi perso, il y avait des trucsque je connaissais pas, doncj'ai bien suivi, mais à mon avis il va falloirque je re-regarde ça en replay quand même.
00:58:49 :Ouais, toutpareil.Il faut déjàune bonne pratique.Oui, il a fallu que j'aie une bonne pratique.De toute façon, sur Doctrine, je vaisreprendre des mentorats Django, là il y en avait plus.
00:59:03 :Mais je vais en reprendre et puis au fur et à mesureon parlera de choses de plus en plus complexes.Et du coup, rapidement surles vues.
00:59:13 :En fait, vous voyez icipour ceux qui ont commencéavec les vues,c'est un chèque d'honneur, ça faisait longtempsque tu les as vues, maisje sais qu'il y en a qui commencent avec la formation Django.
00:59:25 :Donc,j'utilise des vues basées sur les fonctions.Ici,j'utilise un décorateurtask number required, en faitça indique que siune personne veutaccéder à l'URLqu'elle n'est pasadmin,elle serait jetée en fait.
00:59:47 :Et donc, en fait,ce décorateur-là, je l'utilise aussidans mes classes, parce que là c'est une fonction, et j'ai des classes.Et là, j'utilisele décorateur méthode décorateur.
00:59:57 :J'envoie le décorateur que j'ai utilisé sur la méthodeet la méthode qui s'appelle dispatch.Donc là,c'est assez basique, j'utilise desje fais pas malde CRUD,donc la create, update, delete.
01:00:13 :Et donc,quel modèle je veux afficher,j'utilise une pagination,ça m'évite d'afficher mes 10 000 projets d'un coupsur la même page.Ce qui peut être intéressant,inputdans une vue basée sur les fonctions,sur les classes,vous pouvez surchargerpour envoyer plus de contextepuisque vous avez de base dans votre vue.
01:00:41 :Donc ici, par exemple, j'envoieun contexte sur le statuten fait, j'envoie par exemplesur le header de ma page,ça sera marqué création d'un projet.
01:00:51 :Qu'est-ce qui peut être intéressant à voir,c'est ce que vous voyez déjà.Les fields, ok,ça je m'en fiche,ça je m'en fiche,voilà, c'est ici.
01:01:07 :Alors, quand vous êtes sur unquand par exemple vous créez une facture,ici, vous êtes sur unmany-to-many au niveau des services,ici, tous les services,c'est un many-to-many,ça veut dire que de base,de base, si je vais par,je ne sais plus si j'ai découpémon serveur ou pas,
01:01:27 :est-ce qu'il est coupé mon serveur ?Ouais.Pour finir rapidement,hop,truc qu'il est intéressant à faireet qui m'a sorti d'une galère déjà.Donc,si je vais sur là,c'est le Django admin,mon url ici, voilà,si vous créez une facture,vous l'ajoutez,donc là, vous avez tous les services,
01:01:55 :donc imaginez que si vous avez,je ne sais pas, 100 services,et bien ils apparaissent tous.Donc ça va vite être le bordel à sélectionner le bon.
01:02:03 :Donc vous avez même ceux qui ne sont pas facturés,donc là, Paul, ça veut dire pas facturé,Truc, ça veut dire c'est facturé.Donc là, vous avez, même ceux qui sont facturés apparaissent.
01:02:11 :Donc c'est pour ça que je me suis créé, moi, une adminqui fait queles factures, là, si j'en crée une,il n'y a que ceux qui ne sont pas facturés.
01:02:19 :Vous voyez, il n'y a pas tout.Et en fait, pour ça,donc je suis allé dans,donc là, dans ma vue, je me suis créé un formulaire personnalisé,et en fait, dans votre formulaire,je m'appelle, je l'ai appelé comment celui-là,je ne sais plus,serviceform,serviceform,c'est celui-là, attendez,
01:02:43 :ah non, c'est pas créé, c'est sur invoiceform que je voulais,excusez-moi, c'était sur les invoice,invoice, invoice, invoice, invoice,voilà, c'est celui-là, invoiceform,excusez-moi. Donc pour ne pas qu'il y ait
01:02:55 :tous les services qui apparaissent,et bien en fait, je vais aller ciblermonmon champ servicesque j'ai mis,donc qui va être dans la méthode init,en fait, je vais surchanger init,et mon champ,donc je fais un self.fields, donc mon champ services,
01:03:13 :qui sont tous les services de la facture,et bien je vais modifier le core reset,et je vais aller faire un filterpour dire, en gros, je ne vais faire apparaîtreque ceux qui ne sont pas encore facturés.
01:03:23 :Donc là, j'ai bien que ceux qui ne sont pas encore facturés.Voilà.Je ne sais pas s'il y en a qui faisaient déjà ça,par exemple, sur leur form, avec Django,ou pas ?
01:03:33 :Johner, je ne sais pas si tu l'avais déjà fait.Non, non, pas du tout.Et bien, tu vois, ça c'est super pratique,parce que tu peux t'amuser, du coup,à modifier ce qu'il apparaît dans ton champ money-to-money.
01:03:43 :Ouais, ouais.Ouais, non, c'est cool,je vais m'intéresser au truc, ouais, effectivement.Bon, après, je ne vais pas,aller, c'est des vues,enfin, c'est des vues basiques,je fais pas mal de petites choses,mais juste pour finirlà-dessus,sur une,je vais prendreune vue,une vue au hasard,
01:04:11 :voilà. Alors,quand vous avez besoin, des fois,d'utiliser,en fait, un objetdans une vue sur les,basée sur les classes, comme ça,parce qu'il y en a qui peuvent se dire,ouais, mais c'est trop fidgé, les classes,en fait, pas du tout, pas du tout.
01:04:29 :Ici, en fait, je me suis amusé,j'ai redéfini la méthode setup,et en fait, dans la méthode setup,et bien, vous pouvez vous amuserà créer un,un attribut, et en fait, je vais les récupérerà un objet, donc là, c'est un projet,qui est son pk,parce que dans l'URL, en fait, dans
01:04:47 :createService,qui est, qui est,je ne sais plus,create, createService,hum,je suis perdu, createCustomer,createInvoice,je l'avais, laquelle a qui ?addService, ici, et bien,j'utilise un pk,que je réutilise, en fait, ici, que je vais récupérerdans mes paramètres,en argument,et en fait, on peut très bien créer dans une
01:05:15 :vue fondée sur les classes,un attribut dans la méthode setup,et cet attribut, après,et bien, au lieu d'à chaque fois de faire,je pourrais très bien après faire ça,dans chaque méthode, dans les deux ans, je pourrais très bienfaire ça, mais c'est un peu lourd dingue,donc je préfère me créer ici un attribut,
01:05:31 :et puis je le réutilise là,et je le réutilise là, par exemple, voilà.Donc, vous voyez que les classes,on peut très bien s'amuser,on peut très bienfaire des choses flexibles,et puis, sans avoir à chaque foisde toujours écrire.
01:05:47 :Donc,bon, voilà, je ne sais pas déjàà quoi je parle, juste pour info,pour tout ce qui est test,j'utilise ce qu'on appelle PyTest,donc j'ai un petit conflit qui est rapideici,j'ai mon fichier de test qui est à part,j'utilise ce qu'on appelledes factories,ça me permet de créer, en fait, mes instances
01:06:09 :un peu plus rapidement,en renseignant moins de champs, et c'estles champs que je n'ai pas besoin,où je n'ai pas besoin d'être précis,c'est les factories qui vont gérerpour moi, et puis après,je teste toute la logiquelà, où avec tous mes signaux, où à chaque fois
01:06:25 :que je supprime un service, il doit passer enpas facturé, lors passé facturé, ça doit mettreà jour le total de ma facture,et bien, en fait, je teste tout ici,et je teste aussi mes vues, où j'ai faitdes modifications sur des formulaires que j'ai surchargées,et comme ça, j'ai vérifié que tout fonctionne
01:06:39 :bien, donc je ne vais pas dans le détail, parce que là,ça mériteraitencore de parler au moins pendant trois quarts d'heure,mais voilà, doncj'utilise SpyTest, et doncnormalement, si là, je lance SpyTest,tac,et comme ça, ça me permet de voir que je n'ai riencassé au niveau de mes signaux,
01:06:59 :je sais que tout passe, et que toutes les valeurssont bien mises à jour,comme j'ai demandé,donc voilà, rapidement pour les tests,et j'utilise aussi Ruff,et Ruff, ça me permetd'avoir un limiter,et en gros, si je fais un Ruffcheck,je sais que tout est bien,
01:07:19 :mais sinon, ça me dit quequand mon codeest mal formaté, que j'ai des importsqui ne servent à rien, je ne sais pas si je faisun...
01:07:29 :on va finir là-dessus, si par exempledans...il n'y a pas un import que je pourrais faire, si,je pourrais faire unfrom point...non, j'importe déjà,je ne sais pas,je vais le faire dans unautre fichier,de par exemplecustomers ici, si j'aile forms ici,dans les urls,
01:07:57 :il n'y a aucune raisonque j'importeun formulaire dans les urls, mais on va le faire,.forms,import, et j'ai quoi, j'avais serviceform,alors je ne sais pas s'il va le voir tout de suite ou pas,mais normalement, si je relance le terminal,est-ce que si je fais
01:08:15 :un Ruff, est-ce que ça qu'il le voit, je ne sais plus,ouais, voilà, vous voyez, en fait,il va voir tout de suite,qu'il y a un truc qui n'est pas utilisé,en fait,que j'ai un import qui n'est pas utilisé, je ne sais pass'il y en a qui utilisent déjà ça ou pas, Ruff,
01:08:29 :non,pas du tout, ok,ça a l'air sympa,ouais, c'est très sympa, et je sais quedans les boîtes, j'aime bien ça,ceux qui travaillentdans les boîtes,en fait, je l'ai appris en bossant justement avec un gars,il m'a dit, t'inquiète pas,on mettra des linter en place et tout, parce que c'était un peu
01:08:49 :la première fois, j'étais stressé,il m'a parlé de ça, et en fait, maintenant,je suis sur tous mes projets, et c'est comme ça que j'aique j'ai nettoyé tous les imports,parce qu'après, on peut envoyer les commandes,et il va tout supprimer directementtout seul, voilà, bon, moi, ça me fait un peu flipper
01:09:03 :de faire ça, mais je vais le faire,comme,vous envoyez une commande, qui va allerformater votre code, automatiquementaussi, parce que moi, mes imports,à chaque fois, ils sont tous, par exemple,faits à la ligne, en mode bourrin,et je vais envoyer Ruff,qui me les a lui, mis tout seul, comme ça,
01:09:21 :et qui va aller les organiser dans l'ordre,tout seul, voilà.C'est un petitdédié Django, ou c'estutilisable en dehors de Django ?Non, non, non, regarde, Ruff,puis donc,c'est écrit en Rust,hop, et,pourquoi ciret, ça allume, on s'en fout,tac, et voilà, en fait, de toute la
01:09:43 :doc, c'est facile à installer,et en fait, ça fait à la foislinter,et puis aussi,formater pour votre code.Par contre, faites gaffe,parce que, faites gaffe, il n'y a pas trop de disques,si vous envoyez la commande Ruff format,et bien, il va aller le faire tout seul,
01:10:01 :il va aller formater tout votre code, il va vraiment allerremettre à la lignes'il y a besoin ou pas, quoi.Ok.Donc, c'est Ruff, et c'est trop bien.
01:10:11 :Et, moi,j'ai pas trop connu, je sais qu'il y en a qui utilisait,par exemple, Flake 8,Flake 8, Highlint, c'est connu,et ils ont fait des comparaisons,en fait, entre leslinters, et il s'avoueraitque Ruff, en 0,24 secondes,fait le boulot,quand Highlint le fait en plus de 60 secondes.
01:10:31 :Mais, c'est écrit en R,c'est écrit en R, en fait,je ne connais pas le R,mais on m'a souvent dit que le Rétait ultra optimisé, que c'est super rapide.
01:10:43 :Donc,ce qui fait que, du coup,ça marchetrès, très fort.Donc, voilà.Je m'arrête là, je suis désolé, j'ai parlé longtemps,je me rends compte que j'ai présenté des chosespas forcément évidentes, mais...
01:10:59 :Non, c'était cool, c'est toujours biende découvrir des nouvelles choses,donc non, c'est parfait, nickel.Ouais, merci.L'idée, c'était de présenter le projet,donc je voulais présenter un peutout en global, sans trop rentrer en détails non plus,mais de voir un peu les conceptsque j'utilisais, quoi.
01:11:19 :Donc, voilà.Le plus chaud,bon, Wagtail, c'est pas si compliqué que ça,mais je pense que le plus chaud, c'est à la limitequ'on en ait vu Aggregate,les méthodes d'aggrégation,qui étaient dansCustomer, ici, dans lesmodèles.
01:11:39 :Ça, ici.Ça, je prends mon tour là-dessus,de toute façon. Les Aggregate,on a aussi ce qui s'appelle Annotate, avec Django.Je reviendrai plus tard en détail.
01:11:49 :Puis j'ai fait une vidéo YouTube,de toute façon.Ce qui pouvait être chaud aussi, c'étaittous les signaux.Une fois que vous les comprenez, en fait, il n'y a rien de très sorcier.
01:11:59 :Juste sur le principe,c'est que dès que vous allez faire un changementsur un,dans un Many-to-Many,ou sur une instance,vous configurez bien votre signal,et après, Django, il va savoirquand l'attraper, et quoi mettre à jour.
01:12:15 :Voilà.Donc, voilà.C'est tout pour moi.Je m'arrête là. Promis, je me tais.Merci encore une fois, c'était bien cool.Merci.Merci à vous.Merci à vous beaucoup.
01:12:35 :C'est normal,c'est normal, ça fait plaisir de partager.Ça fait plaisir.Il y a du boulot, là.Ouais, ouais, ouais.Il y a du boulot.
01:12:47 :En plus, c'était fait un peu à la va-vite.Parce que j'avais du boulot.Je dois prendre du boulot pour une boîte.J'ai fait ça en vacances, quand j'étais à la montagne.
01:12:55 :L'application, je la faisais le soir, dans le canapé,quand les gamins dormaient.Et je n'ai pas forcément fait les choses bien,j'avoue, quand je l'ai fait. Je l'ai fait les tests en dernier.
01:13:03 :En général,je fais toujours les tests en même temps.Oui, voilà.C'est triste, c'était mon erreur, mais je l'ai fait vraiment à la va-vite.Je me suis dit, il faut que ça marche. Il faut que ça sorte.
Aucune occurrence trouvée pour « ».
Bravo, tu es prêt à passer à la suite