kalo-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/bin/kalo.ts +17 -0
- package/generators/ai-enhancer/index.ts +281 -0
- package/generators/ai-enhancer/keywords.json +1158 -0
- package/generators/constants.ts +52 -0
- package/generators/django-app/index.ts +67 -0
- package/generators/django-app/templates/admin.py.hbs +6 -0
- package/generators/django-app/templates/apps.py.hbs +9 -0
- package/generators/django-app/templates/init.py.hbs +0 -0
- package/generators/django-app/templates/models_init.py.hbs +2 -0
- package/generators/django-app/templates/urls.py.hbs +8 -0
- package/generators/django-app/templates/views.py.hbs +5 -0
- package/generators/django-channel/index.ts +78 -0
- package/generators/django-channel/templates/consumer.py.hbs +47 -0
- package/generators/django-channel/templates/routing.py.hbs +8 -0
- package/generators/django-form/index.ts +62 -0
- package/generators/django-form/templates/form.py.hbs +12 -0
- package/generators/django-form/templates/forms_file.py.hbs +6 -0
- package/generators/django-form/templates/model_form.py.hbs +18 -0
- package/generators/django-view/index.ts +95 -0
- package/generators/django-view/templates/view_cbv.py.hbs +11 -0
- package/generators/django-view/templates/view_fbv.py.hbs +7 -0
- package/generators/django-view/templates/view_template.html.hbs +8 -0
- package/generators/docs/index.ts +36 -0
- package/generators/help/index.ts +84 -0
- package/generators/main/index.ts +429 -0
- package/generators/utils/ai/common.ts +141 -0
- package/generators/utils/ai/index.ts +2 -0
- package/generators/utils/analysis.ts +82 -0
- package/generators/utils/code-manipulation.ts +119 -0
- package/generators/utils/filesystem.ts +64 -0
- package/generators/utils/index.ts +47 -0
- package/generators/utils/plop-actions.ts +61 -0
- package/generators/utils/search.ts +24 -0
- package/generators/wagtail-admin/index.ts +122 -0
- package/generators/wagtail-admin/templates/admin_view.html.hbs +21 -0
- package/generators/wagtail-admin/templates/admin_view.py.hbs +15 -0
- package/generators/wagtail-admin/templates/component.html.hbs +6 -0
- package/generators/wagtail-admin/templates/component.py.hbs +11 -0
- package/generators/wagtail-admin/templates/wagtail_hooks.py.hbs +18 -0
- package/generators/wagtail-block/index.ts +55 -0
- package/generators/wagtail-block/templates/block_class.py.hbs +13 -0
- package/generators/wagtail-block/templates/block_template.html.hbs +5 -0
- package/generators/wagtail-page/actions/model.ts +18 -0
- package/generators/wagtail-page/actions/orderable.ts +21 -0
- package/generators/wagtail-page/actions/page.ts +40 -0
- package/generators/wagtail-page/actions/snippet.ts +19 -0
- package/generators/wagtail-page/index.ts +63 -0
- package/generators/wagtail-page/templates/django_model.py.hbs +18 -0
- package/generators/wagtail-page/templates/orderable_model.py.hbs +21 -0
- package/generators/wagtail-page/templates/page_pair_model.py.hbs +62 -0
- package/generators/wagtail-page/templates/page_template.html.hbs +14 -0
- package/generators/wagtail-page/templates/snippet_model.py.hbs +24 -0
- package/package.json +47 -0
- package/plopfile.ts +26 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,1158 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"terms": [
|
|
4
|
+
"modèle",
|
|
5
|
+
"model",
|
|
6
|
+
"classe",
|
|
7
|
+
"entité",
|
|
8
|
+
"objet métier",
|
|
9
|
+
"table"
|
|
10
|
+
],
|
|
11
|
+
"instruction": "INTENT DETECTED: MODEL DEFINITION. Créer ou modifier un modèle Django. Définir la classe, l'héritage (models.Model ou Page), les Meta options et __str__.",
|
|
12
|
+
"example_output": "class Article(models.Model):\n title = models.CharField(max_length=200)\n class Meta:\n verbose_name = 'Article'\n def __str__(self):\n return self.title",
|
|
13
|
+
"documentation": "Un modèle est la source unique et définitive d'informations sur vos données. Il contient les champs et les comportements essentiels des données que vous stockez. Généralement, chaque modèle correspond à une seule table de base de données.",
|
|
14
|
+
"documentation_officielle": "Un modèle est la source unique et définitive d'informations sur vos données. Il contient les champs et les comportements essentiels des données que vous stockez. Généralement, chaque modèle correspond à une seule table de base de données."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"terms": [
|
|
18
|
+
"data",
|
|
19
|
+
"field",
|
|
20
|
+
"champ",
|
|
21
|
+
"donnée",
|
|
22
|
+
"attribut",
|
|
23
|
+
"colonne",
|
|
24
|
+
"propriété"
|
|
25
|
+
],
|
|
26
|
+
"instruction": "INTENT DETECTED: FIELD. Identifier le modèle cible, définir le type de champ Django approprié (CharField, TextField, IntegerField, etc.), gérer null/blank/default/validators.",
|
|
27
|
+
"example_output": "subtitle = models.CharField(max_length=255, blank=True, null=True, help_text='Sous-titre optionnel')",
|
|
28
|
+
"documentation": "Les champs définissent le type de données stockées dans une colonne de la base de données. Chaque champ est une instance d'une classe Field appropriée (CharField, IntegerField, etc.) qui détermine le type de colonne, la validation et le widget par défaut.",
|
|
29
|
+
"documentation_officielle": "La partie la plus importante d'un modèle – et la seule obligatoire – est la liste des champs de base de données qu'il définit. Les champs sont spécifiés par des attributs de classe."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"terms": [
|
|
33
|
+
"clé primaire",
|
|
34
|
+
"pk",
|
|
35
|
+
"id",
|
|
36
|
+
"identifiant unique",
|
|
37
|
+
"primary key"
|
|
38
|
+
],
|
|
39
|
+
"instruction": "INTENT DETECTED: PRIMARY KEY. Définir explicitement une clé primaire personnalisée ou utiliser AutoField/UUIDField.",
|
|
40
|
+
"example_output": "id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)",
|
|
41
|
+
"documentation": "Une clé primaire est un champ unique identifiant chaque enregistrement dans une table. Par défaut, Django ajoute un champ `id` auto-incrémenté, mais vous pouvez définir votre propre clé primaire en définissant `primary_key=True` sur un champ.",
|
|
42
|
+
"documentation_officielle": "Par défaut, Django donne à chaque modèle une clé primaire auto-incrémentée : id = models.AutoField(primary_key=True). Si vous souhaitez spécifier une clé primaire personnalisée, spécifiez primary_key=True sur l'un de vos champs."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"terms": [
|
|
46
|
+
"index",
|
|
47
|
+
"indexation",
|
|
48
|
+
"performance recherche",
|
|
49
|
+
"db_index"
|
|
50
|
+
],
|
|
51
|
+
"instruction": "INTENT DETECTED: INDEX. Ajouter des index pour optimiser les requêtes. Utiliser db_index=True ou Meta.indexes.",
|
|
52
|
+
"example_output": "class Meta:\n indexes = [models.Index(fields=['slug', '-created_at'])]",
|
|
53
|
+
"documentation": "Les index de base de données accélèrent les opérations de recherche. Django permet de définir des index via l'option `indexes` dans la classe `Meta` du modèle ou avec `db_index=True` sur un champ.",
|
|
54
|
+
"documentation_officielle": "L'option Meta.indexes permet de définir une liste d'index que vous souhaitez créer sur le modèle."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"terms": [
|
|
58
|
+
"contrainte",
|
|
59
|
+
"constraint",
|
|
60
|
+
"unicité",
|
|
61
|
+
"unique",
|
|
62
|
+
"check"
|
|
63
|
+
],
|
|
64
|
+
"instruction": "INTENT DETECTED: CONSTRAINT. Ajouter des contraintes de base de données via Meta.constraints.",
|
|
65
|
+
"example_output": "class Meta:\n constraints = [models.UniqueConstraint(fields=['user', 'product'], name='unique_user_product')]",
|
|
66
|
+
"documentation": "Les contraintes permettent d'imposer des règles au niveau de la base de données, comme l'unicité composite ou des vérifications de conditions (CheckConstraint). Elles sont définies dans la classe `Meta`.",
|
|
67
|
+
"documentation_officielle": "L'option Meta.constraints permet de définir une liste de contraintes que vous souhaitez définir sur le modèle."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"terms": [
|
|
71
|
+
"abstract",
|
|
72
|
+
"abstrait",
|
|
73
|
+
"héritage",
|
|
74
|
+
"base class"
|
|
75
|
+
],
|
|
76
|
+
"instruction": "INTENT DETECTED: ABSTRACT MODEL. Créer un modèle abstrait pour factoriser des champs communs sans créer de table.",
|
|
77
|
+
"example_output": "class TimestampedModel(models.Model):\n created_at = models.DateTimeField(auto_now_add=True)\n class Meta:\n abstract = True",
|
|
78
|
+
"documentation": "Les modèles abstraits sont des classes de base qui ne créent pas de table en base de données. Ils servent à factoriser des champs et méthodes communs pour d'autres modèles qui en héritent.",
|
|
79
|
+
"documentation_officielle": "Les modèles abstraits sont des classes de base dans lesquelles vous définissez des champs que vous souhaitez inclure dans de nombreux modèles enfants. Django ne crée pas de table de base de données pour les modèles abstraits."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"terms": [
|
|
83
|
+
"proxy",
|
|
84
|
+
"modèle proxy",
|
|
85
|
+
"comportement alternatif"
|
|
86
|
+
],
|
|
87
|
+
"instruction": "INTENT DETECTED: PROXY MODEL. Créer un modèle proxy pour modifier le comportement sans nouvelle table.",
|
|
88
|
+
"example_output": "class PublishedArticle(Article):\n class Meta:\n proxy = True\n ordering = ['-published_date']",
|
|
89
|
+
"documentation": "Les modèles proxy permettent de modifier le comportement d'un modèle (méthodes, manager par défaut, méta-options) sans changer le schéma de base de données.",
|
|
90
|
+
"documentation_officielle": "Les modèles proxy sont utilisés pour modifier le comportement d'un modèle (par exemple, pour inclure des méthodes supplémentaires ou modifier le gestionnaire par défaut) sans changer le schéma de base de données."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"terms": [
|
|
94
|
+
"page",
|
|
95
|
+
"type de page",
|
|
96
|
+
"nouvelle page",
|
|
97
|
+
"template",
|
|
98
|
+
"contenu",
|
|
99
|
+
"page wagtail"
|
|
100
|
+
],
|
|
101
|
+
"instruction": "INTENT DETECTED: PAGE TYPE. Créer ou modifier une Page Wagtail. Définir l'héritage de Page, le template, les champs, les panels, parent_page_types et subpage_types.",
|
|
102
|
+
"example_output": "class BlogPage(Page):\n template = 'blog/blog_page.html'\n parent_page_types = ['BlogIndexPage']\n subpage_types = []\n intro = models.TextField(blank=True)\n content_panels = Page.content_panels + [FieldPanel('intro')]",
|
|
103
|
+
"documentation": "Dans Wagtail, les pages sont définies comme des modèles Django héritant de `Page`. Chaque type de page définit ses propres champs et templates, et s'intègre dans l'arborescence de contenu.",
|
|
104
|
+
"documentation_officielle": "La classe Page est le type de base pour tout contenu qui a une URL dans votre site Wagtail. Les modèles de page sont définis comme des modèles Django standard héritant de wagtail.models.Page."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"terms": [
|
|
108
|
+
"page index",
|
|
109
|
+
"listing",
|
|
110
|
+
"liste",
|
|
111
|
+
"index page"
|
|
112
|
+
],
|
|
113
|
+
"instruction": "INTENT DETECTED: INDEX PAGE. Créer une page d'index qui liste des sous-pages. Surcharger get_context pour passer les enfants.",
|
|
114
|
+
"example_output": "class BlogIndexPage(Page):\n def get_context(self, request):\n context = super().get_context(request)\n context['posts'] = BlogPage.objects.child_of(self).live()\n return context",
|
|
115
|
+
"documentation": "Une page d'index (ou listing) est utilisée pour lister d'autres pages (généralement ses enfants). Elle utilise souvent `get_context` pour récupérer et passer les sous-pages au template.",
|
|
116
|
+
"documentation_officielle": "L'option Meta.indexes permet de définir une liste d'index que vous souhaitez créer sur le modèle."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"terms": [
|
|
120
|
+
"routable",
|
|
121
|
+
"routes multiples",
|
|
122
|
+
"sous-urls",
|
|
123
|
+
"routablepagem"
|
|
124
|
+
],
|
|
125
|
+
"instruction": "INTENT DETECTED: ROUTABLE PAGE. Utiliser RoutablePageMixin pour définir plusieurs URLs sous une même page.",
|
|
126
|
+
"example_output": "from wagtail.contrib.routable_page.models import RoutablePageMixin, route\n\nclass BlogIndexPage(RoutablePageMixin, Page):\n @route(r'^tag/(?P<tag>[-\\w]+)/$')\n def tag(self, request, tag):\n posts = self.get_posts().filter(tags__slug=tag)\n return self.render(request, context={'posts': posts})",
|
|
127
|
+
"documentation": "Le `RoutablePageMixin` permet à une page d'intégrer son propre système d'URL, permettant de créer des sous-vues (comme /année/mois/) au sein d'une même page Wagtail sans polluer l'arbre des pages.",
|
|
128
|
+
"documentation_officielle": "Le RoutablePageMixin permet à une page d'intégrer des vues Django standard, permettant à une page de répondre à plusieurs URL sous son URL principale."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"terms": [
|
|
132
|
+
"texte",
|
|
133
|
+
"text",
|
|
134
|
+
"string",
|
|
135
|
+
"chaîne",
|
|
136
|
+
"varchar"
|
|
137
|
+
],
|
|
138
|
+
"instruction": "INTENT DETECTED: TEXT FIELD. Utiliser CharField pour texte court ou TextField pour texte long.",
|
|
139
|
+
"example_output": "title = models.CharField(max_length=200)\ndescription = models.TextField()",
|
|
140
|
+
"documentation": "`CharField` est pour les chaînes courtes de taille fixe (nécessite `max_length`), tandis que `TextField` est pour les grands blocs de texte sans limite de taille stricte.",
|
|
141
|
+
"documentation_officielle": "CharField est un champ de chaîne de caractères, pour les chaînes de petite à grande taille. Pour de grandes quantités de texte, utilisez TextField."
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"terms": [
|
|
145
|
+
"nombre",
|
|
146
|
+
"integer",
|
|
147
|
+
"entier",
|
|
148
|
+
"décimal",
|
|
149
|
+
"float",
|
|
150
|
+
"numérique"
|
|
151
|
+
],
|
|
152
|
+
"instruction": "INTENT DETECTED: NUMERIC FIELD. Choisir IntegerField, DecimalField, FloatField selon le besoin.",
|
|
153
|
+
"example_output": "price = models.DecimalField(max_digits=10, decimal_places=2)\nquantity = models.IntegerField(default=0)",
|
|
154
|
+
"documentation": "`IntegerField` pour les entiers, `DecimalField` pour les nombres décimaux précis (monétaire), et `FloatField` pour les nombres à virgule flottante.",
|
|
155
|
+
"documentation_officielle": "IntegerField est un entier. DecimalField est un nombre décimal à virgule fixe, représenté en Python par une instance de Decimal. FloatField est un nombre à virgule flottante."
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"terms": [
|
|
159
|
+
"boolean",
|
|
160
|
+
"booléen",
|
|
161
|
+
"true/false",
|
|
162
|
+
"oui/non",
|
|
163
|
+
"checkbox"
|
|
164
|
+
],
|
|
165
|
+
"instruction": "INTENT DETECTED: BOOLEAN FIELD. Utiliser BooleanField avec default approprié.",
|
|
166
|
+
"example_output": "is_published = models.BooleanField(default=False)",
|
|
167
|
+
"documentation": "`BooleanField` stocke des valeurs vrai/faux. Utilisez `NullBooleanField` (obsolète, maintenant `BooleanField(null=True)`) si la valeur peut être inconnue.",
|
|
168
|
+
"documentation_officielle": "Un champ vrai/faux. Le widget de formulaire par défaut est une case à cocher (CheckboxInput)."
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"terms": [
|
|
172
|
+
"date",
|
|
173
|
+
"datetime",
|
|
174
|
+
"heure",
|
|
175
|
+
"timestamp",
|
|
176
|
+
"temps"
|
|
177
|
+
],
|
|
178
|
+
"instruction": "INTENT DETECTED: DATE/TIME FIELD. Utiliser DateField, DateTimeField ou TimeField avec auto_now/auto_now_add si nécessaire.",
|
|
179
|
+
"example_output": "published_date = models.DateField()\ncreated_at = models.DateTimeField(auto_now_add=True)\nupdated_at = models.DateTimeField(auto_now=True)",
|
|
180
|
+
"documentation": "`DateField` pour une date, `DateTimeField` pour date et heure. `auto_now_add` définit la date à la création, `auto_now` à chaque modification.",
|
|
181
|
+
"documentation_officielle": "DateField est une date, représentée en Python par une instance de datetime.date. DateTimeField est une date et une heure, représentée par datetime.datetime."
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"terms": [
|
|
185
|
+
"email",
|
|
186
|
+
"courriel",
|
|
187
|
+
"adresse email"
|
|
188
|
+
],
|
|
189
|
+
"instruction": "INTENT DETECTED: EMAIL FIELD. Utiliser EmailField avec validation intégrée.",
|
|
190
|
+
"example_output": "email = models.EmailField(unique=True)",
|
|
191
|
+
"documentation": "`EmailField` est un CharField qui vérifie que la valeur est une adresse email valide grâce à un validateur intégré.",
|
|
192
|
+
"documentation_officielle": "Un CharField qui vérifie que la valeur est une adresse email valide en utilisant EmailValidator."
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"terms": [
|
|
196
|
+
"url",
|
|
197
|
+
"lien",
|
|
198
|
+
"website",
|
|
199
|
+
"site web"
|
|
200
|
+
],
|
|
201
|
+
"instruction": "INTENT DETECTED: URL FIELD. Utiliser URLField avec validation d'URL.",
|
|
202
|
+
"example_output": "website = models.URLField(blank=True)",
|
|
203
|
+
"documentation": "`URLField` est un CharField pour les URL, validé par `URLValidator`.",
|
|
204
|
+
"documentation_officielle": "Un CharField pour une URL, validé par URLValidator."
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"terms": [
|
|
208
|
+
"slug",
|
|
209
|
+
"url-friendly",
|
|
210
|
+
"permalink"
|
|
211
|
+
],
|
|
212
|
+
"instruction": "INTENT DETECTED: SLUG FIELD. Utiliser SlugField, souvent avec unique=True.",
|
|
213
|
+
"example_output": "slug = models.SlugField(max_length=200, unique=True)",
|
|
214
|
+
"documentation": "`SlugField` est un terme générique pour un label court, composé de lettres, chiffres, underscores ou traits d'union, généralement utilisé dans les URLs.",
|
|
215
|
+
"documentation_officielle": "Un slug est un label court pour quelque chose, contenant uniquement des lettres, des chiffres, des underscores ou des traits d'union. Ils sont généralement utilisés dans les URL."
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"terms": [
|
|
219
|
+
"json",
|
|
220
|
+
"jsonfield",
|
|
221
|
+
"données structurées"
|
|
222
|
+
],
|
|
223
|
+
"instruction": "INTENT DETECTED: JSON FIELD. Utiliser JSONField pour stocker des données JSON.",
|
|
224
|
+
"example_output": "metadata = models.JSONField(default=dict, blank=True)",
|
|
225
|
+
"documentation": "`JSONField` permet de stocker des structures de données JSON arbitraires. Il supporte les requêtes sur les clés JSON (sur PostgreSQL notamment).",
|
|
226
|
+
"documentation_officielle": "Un champ pour stocker des données encodées en JSON. En Python, les données sont représentées par leur format natif (dict, list, etc.)."
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"terms": [
|
|
230
|
+
"fichier",
|
|
231
|
+
"upload",
|
|
232
|
+
"file"
|
|
233
|
+
],
|
|
234
|
+
"instruction": "INTENT DETECTED: FILE FIELD. Utiliser FileField avec upload_to.",
|
|
235
|
+
"example_output": "attachment = models.FileField(upload_to='attachments/', blank=True)",
|
|
236
|
+
"documentation": "`FileField` gère le téléchargement de fichiers. `upload_to` détermine le répertoire de stockage. `ImageField` est une spécialisation avec validation d'image.",
|
|
237
|
+
"documentation_officielle": "Un champ de téléchargement de fichier. Nécessite l'argument upload_to pour spécifier le répertoire de stockage."
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"terms": [
|
|
241
|
+
"choix",
|
|
242
|
+
"choices",
|
|
243
|
+
"select",
|
|
244
|
+
"dropdown",
|
|
245
|
+
"options"
|
|
246
|
+
],
|
|
247
|
+
"instruction": "INTENT DETECTED: CHOICE FIELD. Définir des choices avec TextChoices ou IntegerChoices.",
|
|
248
|
+
"example_output": "class Status(models.TextChoices):\n DRAFT = 'draft', 'Brouillon'\n PUBLISHED = 'published', 'Publié'\n\nstatus = models.CharField(max_length=20, choices=Status.choices, default=Status.DRAFT)",
|
|
249
|
+
"documentation": "L'argument `choices` limite les valeurs possibles d'un champ. Il utilise souvent des classes `TextChoices` ou `IntegerChoices` pour définir des énumérations lisibles.",
|
|
250
|
+
"documentation_officielle": "L'argument choices est une séquence d'itérables contenant exactement deux éléments (valeur stockée, étiquette lisible) à utiliser comme choix pour un champ."
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"terms": [
|
|
254
|
+
"relation",
|
|
255
|
+
"liaison",
|
|
256
|
+
"foreignkey",
|
|
257
|
+
"clé étrangère",
|
|
258
|
+
"many-to-one"
|
|
259
|
+
],
|
|
260
|
+
"instruction": "INTENT DETECTED: FOREIGN KEY. Créer une relation many-to-one avec ForeignKey. Définir on_delete et related_name.",
|
|
261
|
+
"example_output": "author = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='articles')",
|
|
262
|
+
"documentation": "Une relation plusieurs-à-un. Nécessite un argument positionnel : la classe à laquelle le modèle est lié. `on_delete` définit le comportement lors de la suppression de l'objet lié.",
|
|
263
|
+
"documentation_officielle": "Une relation plusieurs-à-un. Nécessite un argument positionnel : la classe à laquelle le modèle est lié."
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"terms": [
|
|
267
|
+
"many to many",
|
|
268
|
+
"plusieurs à plusieurs",
|
|
269
|
+
"m2m",
|
|
270
|
+
"manytomany"
|
|
271
|
+
],
|
|
272
|
+
"instruction": "INTENT DETECTED: MANY TO MANY. Créer une relation many-to-many avec ManyToManyField.",
|
|
273
|
+
"example_output": "tags = models.ManyToManyField('Tag', related_name='articles', blank=True)",
|
|
274
|
+
"documentation": "Une relation plusieurs-à-plusieurs. Crée une table intermédiaire pour lier les enregistrements des deux modèles.",
|
|
275
|
+
"documentation_officielle": "Une relation plusieurs-à-plusieurs. Nécessite un argument positionnel : la classe à laquelle le modèle est lié."
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"terms": [
|
|
279
|
+
"one to one",
|
|
280
|
+
"un à un",
|
|
281
|
+
"onetoone"
|
|
282
|
+
],
|
|
283
|
+
"instruction": "INTENT DETECTED: ONE TO ONE. Créer une relation one-to-one avec OneToOneField.",
|
|
284
|
+
"example_output": "profile = models.OneToOneField('UserProfile', on_delete=models.CASCADE)",
|
|
285
|
+
"documentation": "Une relation un-à-un. Similaire à une ForeignKey avec `unique=True`, mais le côté inverse renvoie un seul objet.",
|
|
286
|
+
"documentation_officielle": "Une relation un-à-un. Conceptuellement, c'est similaire à une ForeignKey avec unique=True, mais le côté 'inverse' de la relation renvoie directement un seul objet."
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"terms": [
|
|
290
|
+
"parental",
|
|
291
|
+
"parentalkey",
|
|
292
|
+
"enfant",
|
|
293
|
+
"parent",
|
|
294
|
+
"relation wagtail"
|
|
295
|
+
],
|
|
296
|
+
"instruction": "INTENT DETECTED: PARENTAL KEY. Utiliser ParentalKey pour relations parent-enfant dans Wagtail avec inline editing.",
|
|
297
|
+
"example_output": "from modelcluster.fields import ParentalKey\n\npage = ParentalKey('BlogPage', related_name='gallery_images', on_delete=models.CASCADE)",
|
|
298
|
+
"documentation": "Spécifique à Wagtail (via `django-modelcluster`). Similaire à ForeignKey, mais l'objet enfant est considéré comme faisant partie du parent, essentiel pour les relations inline dans l'éditeur (comme les galeries d'images).",
|
|
299
|
+
"documentation_officielle": "Une ParentalKey est similaire à une ForeignKey, mais elle définit également que l'objet enfant 'appartient' au parent, ce qui est essentiel pour les relations éditables en ligne (InlinePanel) dans Wagtail."
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"terms": [
|
|
303
|
+
"parental many to many",
|
|
304
|
+
"clusterable",
|
|
305
|
+
"m2m wagtail"
|
|
306
|
+
],
|
|
307
|
+
"instruction": "INTENT DETECTED: PARENTAL M2M. Utiliser ParentalManyToManyField pour relations many-to-many éditables inline.",
|
|
308
|
+
"example_output": "from modelcluster.fields import ParentalManyToManyField\n\ncategories = ParentalManyToManyField('Category', blank=True)",
|
|
309
|
+
"documentation": "Spécifique à Wagtail. Permet de gérer des relations ManyToMany directement dans l'interface d'édition de la page (ex: tags, catégories) sans sauvegarder immédiatement.",
|
|
310
|
+
"documentation_officielle": "ParentalManyToManyField est une sous-classe de ManyToManyField qui permet aux objets liés d'être attachés à une instance de modèle qui n'a pas encore été sauvegardée (en utilisant django-modelcluster)."
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"terms": [
|
|
314
|
+
"orderable",
|
|
315
|
+
"ordre",
|
|
316
|
+
"tri",
|
|
317
|
+
"réorganiser",
|
|
318
|
+
"position",
|
|
319
|
+
"inline orderable"
|
|
320
|
+
],
|
|
321
|
+
"instruction": "INTENT DETECTED: ORDERABLE. Hériter de Orderable pour gérer le tri manuel dans l'admin avec drag & drop.",
|
|
322
|
+
"example_output": "from modelcluster.models import ClusterableModel\nfrom wagtail.models import Orderable\n\nclass GalleryImage(Orderable):\n page = ParentalKey('BlogPage', related_name='gallery_images')\n image = models.ForeignKey('wagtailimages.Image', on_delete=models.CASCADE)\n caption = models.CharField(max_length=250, blank=True)",
|
|
323
|
+
"documentation": "Mixin Wagtail permettant de rendre des objets triables (via drag-and-drop) dans l'admin, souvent utilisé avec `InlinePanel`.",
|
|
324
|
+
"documentation_officielle": "Orderable est un modèle abstrait qui ajoute un champ 'sort_order' de type entier pour permettre le tri manuel des objets."
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"terms": [
|
|
328
|
+
"bloc",
|
|
329
|
+
"block",
|
|
330
|
+
"stream",
|
|
331
|
+
"streamfield",
|
|
332
|
+
"contenu flexible",
|
|
333
|
+
"champ flexible",
|
|
334
|
+
"modular content"
|
|
335
|
+
],
|
|
336
|
+
"instruction": "INTENT DETECTED: STREAMFIELD. Ajouter un StreamField avec use_json_field=True. Définir les blocks disponibles.",
|
|
337
|
+
"example_output": "from wagtail.fields import StreamField\nfrom wagtail import blocks\n\nbody = StreamField([\n ('heading', blocks.CharBlock()),\n ('paragraph', blocks.RichTextBlock()),\n ('image', ImageChooserBlock()),\n], use_json_field=True, blank=True)",
|
|
338
|
+
"documentation": "Un champ Wagtail puissant permettant aux éditeurs de construire des pages en assemblant une séquence de blocs de contenu de différents types (texte, image, vidéo, etc.).",
|
|
339
|
+
"documentation_officielle": "StreamField fournit un modèle d'édition de contenu adapté aux pages qui ne suivent pas une structure fixe (comme des articles de blog), où le texte peut être entremêlé d'images et d'autres blocs."
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"terms": [
|
|
343
|
+
"struct",
|
|
344
|
+
"structblock",
|
|
345
|
+
"structure",
|
|
346
|
+
"composite",
|
|
347
|
+
"groupe",
|
|
348
|
+
"bloc composite"
|
|
349
|
+
],
|
|
350
|
+
"instruction": "INTENT DETECTED: STRUCTBLOCK. Créer un StructBlock pour regrouper plusieurs champs cohérents.",
|
|
351
|
+
"example_output": "class HeroBlock(blocks.StructBlock):\n title = blocks.CharBlock(max_length=200)\n text = blocks.TextBlock()\n button_text = blocks.CharBlock(required=False)\n button_link = blocks.URLBlock(required=False)\n \n class Meta:\n icon = 'hero'\n template = 'blocks/hero_block.html'",
|
|
352
|
+
"documentation": "Un bloc StreamField composé de plusieurs sous-blocs fixes (ex: un titre, un texte et une image regroupés). Permet de créer des structures complexes.",
|
|
353
|
+
"documentation_officielle": "Un StructBlock est un bloc conteneur qui regroupe plusieurs blocs enfants (champs) de types différents en une seule valeur structurée."
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"terms": [
|
|
357
|
+
"liste",
|
|
358
|
+
"list",
|
|
359
|
+
"listblock",
|
|
360
|
+
"répétition",
|
|
361
|
+
"multiple",
|
|
362
|
+
"collection"
|
|
363
|
+
],
|
|
364
|
+
"instruction": "INTENT DETECTED: LISTBLOCK. Utiliser ListBlock pour permettre la répétition d'éléments.",
|
|
365
|
+
"example_output": "features = blocks.ListBlock(blocks.CharBlock(max_length=100))",
|
|
366
|
+
"documentation": "Un bloc StreamField qui contient une liste variable d'un même type de sous-bloc.",
|
|
367
|
+
"documentation_officielle": "Un ListBlock est un bloc conteneur qui gère une liste de sous-blocs du même type."
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"terms": [
|
|
371
|
+
"stream",
|
|
372
|
+
"streamblock",
|
|
373
|
+
"nested stream",
|
|
374
|
+
"stream imbriqué"
|
|
375
|
+
],
|
|
376
|
+
"instruction": "INTENT DETECTED: STREAMBLOCK. Créer un StreamBlock pour des structures flexibles imbriquées.",
|
|
377
|
+
"example_output": "class ColumnBlock(blocks.StreamBlock):\n heading = blocks.CharBlock()\n paragraph = blocks.RichTextBlock()\n image = ImageChooserBlock()",
|
|
378
|
+
"documentation": "Un bloc conteneur qui permet de choisir parmi un ensemble de types de blocs enfants, permettant une structure imbriquée flexible.",
|
|
379
|
+
"documentation_officielle": "Un StreamBlock est un bloc conteneur qui permet aux éditeurs de choisir parmi un ensemble de types de blocs et de les ordonner librement."
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"terms": [
|
|
383
|
+
"static",
|
|
384
|
+
"staticblock",
|
|
385
|
+
"bloc statique",
|
|
386
|
+
"fixed"
|
|
387
|
+
],
|
|
388
|
+
"instruction": "INTENT DETECTED: STATICBLOCK. Utiliser StaticBlock pour des marqueurs sans données.",
|
|
389
|
+
"example_output": "separator = blocks.StaticBlock(admin_text='Séparateur horizontal')",
|
|
390
|
+
"documentation": "Un bloc qui n'a pas de valeur stockée, utile pour afficher du texte statique ou des séparateurs dans l'interface d'édition.",
|
|
391
|
+
"documentation_officielle": "Un StaticBlock est un bloc qui n'a pas de données éditables, mais qui peut afficher du contenu statique dans l'interface d'administration ou le template."
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"terms": [
|
|
395
|
+
"page chooser",
|
|
396
|
+
"sélecteur page",
|
|
397
|
+
"lien page"
|
|
398
|
+
],
|
|
399
|
+
"instruction": "INTENT DETECTED: PAGE CHOOSER BLOCK. Utiliser PageChooserBlock pour sélectionner une page.",
|
|
400
|
+
"example_output": "related_page = blocks.PageChooserBlock(required=False, target_model='blog.BlogPage')",
|
|
401
|
+
"documentation": "Un bloc permettant à l'éditeur de sélectionner une page interne Wagtail.",
|
|
402
|
+
"documentation_officielle": "Un bloc permettant de sélectionner une page Wagtail existante."
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"terms": [
|
|
406
|
+
"snippet chooser",
|
|
407
|
+
"sélecteur snippet"
|
|
408
|
+
],
|
|
409
|
+
"instruction": "INTENT DETECTED: SNIPPET CHOOSER BLOCK. Utiliser SnippetChooserBlock pour sélectionner un snippet.",
|
|
410
|
+
"example_output": "author = blocks.SnippetChooserBlock(target_model='blog.Author')",
|
|
411
|
+
"documentation": "Un bloc permettant de sélectionner un snippet existant.",
|
|
412
|
+
"documentation_officielle": "Un bloc permettant de sélectionner un snippet existant."
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"terms": [
|
|
416
|
+
"texte riche",
|
|
417
|
+
"richtext",
|
|
418
|
+
"wysiwyg",
|
|
419
|
+
"éditeur riche"
|
|
420
|
+
],
|
|
421
|
+
"instruction": "INTENT DETECTED: RICHTEXT FIELD. Utiliser RichTextField avec features personnalisables.",
|
|
422
|
+
"example_output": "from wagtail.fields import RichTextField\n\ncontent = RichTextField(features=['bold', 'italic', 'link', 'ol', 'ul', 'h2', 'h3'])",
|
|
423
|
+
"documentation": "Champ stockant du HTML riche. Dans l'admin, il s'affiche comme un éditeur WYSIWYG. Les liens et images internes sont stockés dans un format spécial pour maintenir l'intégrité référentielle.",
|
|
424
|
+
"documentation_officielle": "RichTextField fournit un champ d'édition WYSIWYG pour créer du contenu HTML riche, avec gestion des liens internes et des images Wagtail."
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
"terms": [
|
|
428
|
+
"richtext block",
|
|
429
|
+
"bloc texte riche"
|
|
430
|
+
],
|
|
431
|
+
"instruction": "INTENT DETECTED: RICHTEXT BLOCK. Utiliser RichTextBlock dans StreamField avec features.",
|
|
432
|
+
"example_output": "text = blocks.RichTextBlock(features=['bold', 'italic', 'link'], required=False)",
|
|
433
|
+
"documentation": "L'équivalent de `RichTextField` mais sous forme de bloc pour StreamField.",
|
|
434
|
+
"documentation_officielle": "RichTextBlock est l'équivalent de RichTextField mais destiné à être utilisé à l'intérieur d'un StreamField."
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"terms": [
|
|
438
|
+
"features",
|
|
439
|
+
"fonctionnalités éditeur",
|
|
440
|
+
"toolbar"
|
|
441
|
+
],
|
|
442
|
+
"instruction": "INTENT DETECTED: RICHTEXT FEATURES. Configurer les features disponibles dans l'éditeur richtext.",
|
|
443
|
+
"example_output": "# Dans settings.py\nWAGTAILADMIN_RICH_TEXT_EDITORS = {\n 'default': {\n 'WIDGET': 'wagtail.admin.rich_text.DraftailRichTextArea',\n 'OPTIONS': {'features': ['h2', 'h3', 'bold', 'italic', 'link', 'document-link']}\n }\n}",
|
|
444
|
+
"documentation": "Permet de restreindre ou d'étendre les options de formatage (gras, italique, liens, h2, etc.) disponibles dans l'éditeur riche.",
|
|
445
|
+
"documentation_officielle": "Les fonctionnalités de l'éditeur de texte riche (comme 'bold', 'italic', 'h2') peuvent être configurées globalement ou par champ pour restreindre ou étendre les options disponibles."
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"terms": [
|
|
449
|
+
"image",
|
|
450
|
+
"photo",
|
|
451
|
+
"visuel",
|
|
452
|
+
"picture"
|
|
453
|
+
],
|
|
454
|
+
"instruction": "INTENT DETECTED: IMAGE. Utiliser ForeignKey vers wagtailimages.Image avec renditions.",
|
|
455
|
+
"example_output": "image = models.ForeignKey(\n 'wagtailimages.Image',\n null=True,\n blank=True,\n on_delete=models.SET_NULL,\n related_name='+'\n)",
|
|
456
|
+
"documentation": "Wagtail gère les images via son propre modèle `wagtailimages.Image`, offrant des fonctionnalités avancées de traitement (renditions, point focal).",
|
|
457
|
+
"documentation_officielle": "Wagtail fournit un modèle d'image intégré (wagtailimages.Image) qui gère le stockage et le traitement des images, y compris la détection des points focaux."
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"terms": [
|
|
461
|
+
"image chooser",
|
|
462
|
+
"sélecteur image",
|
|
463
|
+
"chooser image"
|
|
464
|
+
],
|
|
465
|
+
"instruction": "INTENT DETECTED: IMAGE CHOOSER BLOCK. Utiliser ImageChooserBlock dans StreamField.",
|
|
466
|
+
"example_output": "from wagtail.images.blocks import ImageChooserBlock\n\nimage = ImageChooserBlock(required=False)",
|
|
467
|
+
"documentation": "Bloc permettant de sélectionner une image de la bibliothèque Wagtail dans un StreamField.",
|
|
468
|
+
"documentation_officielle": "Wagtail fournit un modèle d'image intégré (wagtailimages.Image) qui gère le stockage et le traitement des images, y compris la détection des points focaux."
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"terms": [
|
|
472
|
+
"rendition",
|
|
473
|
+
"taille image",
|
|
474
|
+
"format image",
|
|
475
|
+
"crop",
|
|
476
|
+
"resize"
|
|
477
|
+
],
|
|
478
|
+
"instruction": "INTENT DETECTED: IMAGE RENDITION. Générer des renditions d'image dans le template.",
|
|
479
|
+
"example_output": "{% load wagtailimages_tags %}\n{% image page.image fill-800x400 %}\n{% image page.image max-1200x800 as hero_img %}",
|
|
480
|
+
"documentation": "Processus de génération de versions redimensionnées ou recadrées des images à la volée dans les templates (ex: `fill-800x600`).",
|
|
481
|
+
"documentation_officielle": "Wagtail fournit un modèle d'image intégré (wagtailimages.Image) qui gère le stockage et le traitement des images, y compris la détection des points focaux."
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"terms": [
|
|
485
|
+
"document",
|
|
486
|
+
"fichier",
|
|
487
|
+
"pdf",
|
|
488
|
+
"download"
|
|
489
|
+
],
|
|
490
|
+
"instruction": "INTENT DETECTED: DOCUMENT. Utiliser ForeignKey vers wagtaildocs.Document.",
|
|
491
|
+
"example_output": "document = models.ForeignKey(\n 'wagtaildocs.Document',\n null=True,\n blank=True,\n on_delete=models.SET_NULL,\n related_name='+'\n)",
|
|
492
|
+
"documentation": "Modèle Wagtail pour gérer les fichiers téléchargeables (PDF, Doc, etc.) avec suivi d'usage.",
|
|
493
|
+
"documentation_officielle": "Le modèle Document (wagtaildocs.Document) gère les fichiers téléchargés qui ne sont pas des images (comme les PDF ou les documents Word)."
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"terms": [
|
|
497
|
+
"document chooser",
|
|
498
|
+
"sélecteur document"
|
|
499
|
+
],
|
|
500
|
+
"instruction": "INTENT DETECTED: DOCUMENT CHOOSER BLOCK. Utiliser DocumentChooserBlock.",
|
|
501
|
+
"example_output": "from wagtail.documents.blocks import DocumentChooserBlock\n\nfile = DocumentChooserBlock(required=False)",
|
|
502
|
+
"documentation": "Bloc permettant de sélectionner un document dans un StreamField.",
|
|
503
|
+
"documentation_officielle": "Le modèle Document (wagtaildocs.Document) gère les fichiers téléchargés qui ne sont pas des images (comme les PDF ou les documents Word)."
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"terms": [
|
|
507
|
+
"embed",
|
|
508
|
+
"video",
|
|
509
|
+
"média externe",
|
|
510
|
+
"oembed"
|
|
511
|
+
],
|
|
512
|
+
"instruction": "INTENT DETECTED: EMBED. Utiliser EmbedBlock pour YouTube, Vimeo, etc.",
|
|
513
|
+
"example_output": "from wagtail.embeds.blocks import EmbedBlock\n\nvideo = EmbedBlock(required=False, help_text='URL YouTube ou Vimeo')",
|
|
514
|
+
"documentation": "Gère l'intégration de contenus externes (oEmbed) comme YouTube ou Vimeo simplement en collant l'URL.",
|
|
515
|
+
"documentation_officielle": "Le module Embeds permet d'intégrer du contenu externe (comme des vidéos YouTube ou des tweets) simplement en fournissant l'URL, en utilisant le standard oEmbed."
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"terms": [
|
|
519
|
+
"dashboard",
|
|
520
|
+
"admin",
|
|
521
|
+
"ui admin",
|
|
522
|
+
"backoffice",
|
|
523
|
+
"éditeur",
|
|
524
|
+
"panels"
|
|
525
|
+
],
|
|
526
|
+
"instruction": "INTENT DETECTED: ADMIN PANELS. Configurer l'interface d'édition avec FieldPanel, InlinePanel, MultiFieldPanel.",
|
|
527
|
+
"example_output": "from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel\n\ncontent_panels = Page.content_panels + [\n FieldPanel('subtitle'),\n MultiFieldPanel([\n FieldPanel('date'),\n FieldPanel('author'),\n ], heading='Métadonnées'),\n InlinePanel('gallery_images', label='Images'),\n]",
|
|
528
|
+
"documentation": "Les `Panels` définissent comment les champs du modèle sont présentés dans l'interface d'édition Wagtail. Ils remplacent `admin.py` de Django pour les Pages.",
|
|
529
|
+
"documentation_officielle": "Les panneaux (Panels) sont des classes qui définissent comment les champs d'un modèle sont présentés dans l'interface d'édition de Wagtail."
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"terms": [
|
|
533
|
+
"inline",
|
|
534
|
+
"inlinepanel",
|
|
535
|
+
"relation inline",
|
|
536
|
+
"nested"
|
|
537
|
+
],
|
|
538
|
+
"instruction": "INTENT DETECTED: INLINE PANEL. Ajouter un InlinePanel pour éditer des relations inline.",
|
|
539
|
+
"example_output": "InlinePanel('related_links', label='Liens associés', min_num=0, max_num=5)",
|
|
540
|
+
"documentation": "Permet d'éditer des objets liés (enfants) directement dans la page d'édition du parent (ex: diapositives d'un carrousel).",
|
|
541
|
+
"documentation_officielle": "InlinePanel permet l'édition d'objets liés (généralement via une ParentalKey) directement dans l'interface d'édition du modèle parent."
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
"terms": [
|
|
545
|
+
"fieldpanel",
|
|
546
|
+
"field panel",
|
|
547
|
+
"champ éditable"
|
|
548
|
+
],
|
|
549
|
+
"instruction": "INTENT DETECTED: FIELD PANEL. Exposer un champ dans l'admin avec FieldPanel.",
|
|
550
|
+
"example_output": "FieldPanel('title', classname='title')",
|
|
551
|
+
"documentation": "Le panneau de base pour éditer un champ de modèle. Il choisit automatiquement le widget approprié.",
|
|
552
|
+
"documentation_officielle": "La partie la plus importante d'un modèle – et la seule obligatoire – est la liste des champs de base de données qu'il définit. Les champs sont spécifiés par des attributs de classe."
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
"terms": [
|
|
556
|
+
"multifieldpanel",
|
|
557
|
+
"groupe champs",
|
|
558
|
+
"fieldset"
|
|
559
|
+
],
|
|
560
|
+
"instruction": "INTENT DETECTED: MULTI FIELD PANEL. Regrouper plusieurs champs sous un heading.",
|
|
561
|
+
"example_output": "MultiFieldPanel([\n FieldPanel('start_date'),\n FieldPanel('end_date'),\n], heading='Période', classname='collapsible')",
|
|
562
|
+
"documentation": "Regroupe visuellement plusieurs panneaux sous un titre commun, et peut être repliable.",
|
|
563
|
+
"documentation_officielle": "MultiFieldPanel regroupe une collection de panneaux enfants, avec un titre optionnel."
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"terms": [
|
|
567
|
+
"tabs",
|
|
568
|
+
"onglets",
|
|
569
|
+
"edit handler",
|
|
570
|
+
"tabbed"
|
|
571
|
+
],
|
|
572
|
+
"instruction": "INTENT DETECTED: TABS. Organiser l'interface en onglets avec TabbedInterface.",
|
|
573
|
+
"example_output": "from wagtail.admin.panels import TabbedInterface\n\nedit_handler = TabbedInterface([\n ObjectList(content_panels, heading='Contenu'),\n ObjectList(promote_panels, heading='SEO'),\n ObjectList(settings_panels, heading='Paramètres'),\n])",
|
|
574
|
+
"documentation": "`TabbedInterface` permet d'organiser les panneaux dans différents onglets (Contenu, Promote, Paramètres) pour clarifier l'interface.",
|
|
575
|
+
"documentation_officielle": "TabbedInterface permet d'organiser les panneaux en plusieurs onglets (comme 'Contenu', 'Promouvoir', 'Paramètres')."
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"terms": [
|
|
579
|
+
"promote",
|
|
580
|
+
"seo",
|
|
581
|
+
"référencement",
|
|
582
|
+
"meta"
|
|
583
|
+
],
|
|
584
|
+
"instruction": "INTENT DETECTED: SEO PANELS. Configurer promote_panels avec champs SEO.",
|
|
585
|
+
"example_output": "promote_panels = Page.promote_panels + [\n FieldPanel('seo_title'),\n FieldPanel('search_description'),\n FieldPanel('search_image'),\n]",
|
|
586
|
+
"documentation": "Champs standards (titre SEO, description meta) pour optimiser le référencement naturel des pages.",
|
|
587
|
+
"documentation_officielle": "Wagtail fournit des champs standard (slug, seo_title, search_description) regroupés dans promote_panels pour gérer le référencement."
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
"terms": [
|
|
591
|
+
"settings",
|
|
592
|
+
"paramètres page",
|
|
593
|
+
"settings panels"
|
|
594
|
+
],
|
|
595
|
+
"instruction": "INTENT DETECTED: SETTINGS PANELS. Ajouter des paramètres techniques dans settings_panels.",
|
|
596
|
+
"example_output": "settings_panels = Page.settings_panels + [\n FieldPanel('show_in_menus'),\n FieldPanel('go_live_at'),\n FieldPanel('expire_at'),\n]",
|
|
597
|
+
"documentation": "Champs de configuration de la page (date de publication, visibilité dans les menus, etc.).",
|
|
598
|
+
"documentation_officielle": "Les settings_panels contiennent les champs de configuration de la page, tels que la date de publication et la visibilité dans les menus."
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"terms": [
|
|
602
|
+
"snippet",
|
|
603
|
+
"réutilisable",
|
|
604
|
+
"global content",
|
|
605
|
+
"contenu global"
|
|
606
|
+
],
|
|
607
|
+
"instruction": "INTENT DETECTED: SNIPPET. Créer un snippet réutilisable avec @register_snippet.",
|
|
608
|
+
"example_output": "from wagtail.snippets.models import register_snippet\nfrom wagtail.admin.panels import FieldPanel\n\n@register_snippet\nclass Author(models.Model):\n name = models.CharField(max_length=100)\n bio = models.TextField()\n panels = [FieldPanel('name'), FieldPanel('bio')]",
|
|
609
|
+
"documentation": "Contenu réutilisable qui n'a pas besoin de structure arborescente (ex: Auteurs, Publicités, Catégories). Géré via le menu Snippets.",
|
|
610
|
+
"documentation_officielle": "Les snippets sont des morceaux de contenu réutilisables (comme des auteurs ou des catégories) qui n'ont pas besoin de faire partie de l'arborescence hiérarchique des pages."
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
"terms": [
|
|
614
|
+
"snippet chooser field",
|
|
615
|
+
"relation snippet"
|
|
616
|
+
],
|
|
617
|
+
"instruction": "INTENT DETECTED: SNIPPET RELATION. Créer une ForeignKey vers un snippet.",
|
|
618
|
+
"example_output": "author = models.ForeignKey('blog.Author', null=True, blank=True, on_delete=models.SET_NULL)",
|
|
619
|
+
"documentation": "Lier une page à un snippet via une ForeignKey.",
|
|
620
|
+
"documentation_officielle": "Les snippets sont des morceaux de contenu réutilisables (comme des auteurs ou des catégories) qui n'ont pas besoin de faire partie de l'arborescence hiérarchique des pages."
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"terms": [
|
|
624
|
+
"contexte",
|
|
625
|
+
"context",
|
|
626
|
+
"data template",
|
|
627
|
+
"variable template",
|
|
628
|
+
"get_context"
|
|
629
|
+
],
|
|
630
|
+
"instruction": "INTENT DETECTED: TEMPLATE CONTEXT. Étendre get_context pour passer des données au template.",
|
|
631
|
+
"example_output": "def get_context(self, request, *args, **kwargs):\n context = super().get_context(request, *args, **kwargs)\n context['recent_posts'] = BlogPage.objects.live().order_by('-first_published_at')[:5]\n return context",
|
|
632
|
+
"documentation": "La méthode `get_context` permet d'injecter des variables supplémentaires dans le template lors du rendu de la page.",
|
|
633
|
+
"documentation_officielle": "La méthode get_context() est utilisée pour préparer les données (le contexte) qui seront passées au template lors du rendu de la page."
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"terms": [
|
|
637
|
+
"vue",
|
|
638
|
+
"view",
|
|
639
|
+
"logique",
|
|
640
|
+
"serve",
|
|
641
|
+
"render"
|
|
642
|
+
],
|
|
643
|
+
"instruction": "INTENT DETECTED: VIEW LOGIC. Surcharger serve() pour logique de rendu personnalisée.",
|
|
644
|
+
"example_output": "def serve(self, request, *args, **kwargs):\n if request.method == 'POST':\n # Handle form\n pass\n return super().serve(request, *args, **kwargs)",
|
|
645
|
+
"documentation": "La méthode `serve` contrôle comment la page répond à la requête HTTP. Elle peut être surchargée pour gérer des formulaires ou des réponses personnalisées.",
|
|
646
|
+
"documentation_officielle": "La méthode serve() est responsable de renvoyer une réponse HTTP pour la page. Elle peut être surchargée pour gérer des interactions complexes comme le traitement de formulaires."
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
"terms": [
|
|
650
|
+
"template",
|
|
651
|
+
"gabarit",
|
|
652
|
+
"html",
|
|
653
|
+
"rendu"
|
|
654
|
+
],
|
|
655
|
+
"instruction": "INTENT DETECTED: TEMPLATE. Définir le template associé à une page.",
|
|
656
|
+
"example_output": "template = 'blog/blog_page.html'\n# ou\ndef get_template(self, request):\n if request.is_ajax():\n return 'blog/blog_page_ajax.html'\n return 'blog/blog_page.html'",
|
|
657
|
+
"documentation": "Fichier HTML utilisant le langage de gabarit Django (DTL) pour afficher dynamiquement les données.",
|
|
658
|
+
"documentation_officielle": "Un template Django est un fichier texte (souvent du HTML) qui utilise le langage de gabarit de Django pour générer dynamiquement du contenu."
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"terms": [
|
|
662
|
+
"requête",
|
|
663
|
+
"query",
|
|
664
|
+
"queryset",
|
|
665
|
+
"filtre",
|
|
666
|
+
"filter",
|
|
667
|
+
"recherche"
|
|
668
|
+
],
|
|
669
|
+
"instruction": "INTENT DETECTED: QUERYSET. Écrire une requête ORM Django avec filtres et optimisations.",
|
|
670
|
+
"example_output": "articles = ArticlePage.objects.live().public().filter(\n status='published'\n).select_related('author').prefetch_related('tags').order_by('-first_published_at')",
|
|
671
|
+
"documentation": "Une collection d'objets de la base de données. Les QuerySets sont paresseux (lazy) : la requête SQL n'est exécutée que lorsque les données sont nécessaires.",
|
|
672
|
+
"documentation_officielle": "Un QuerySet représente une collection d'objets de la base de données. Il est évaluable de manière paresseuse (lazy) et permet de filtrer, trier et découper les résultats."
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
"terms": [
|
|
676
|
+
"pagination",
|
|
677
|
+
"paginate",
|
|
678
|
+
"page par page"
|
|
679
|
+
],
|
|
680
|
+
"instruction": "INTENT DETECTED: PAGINATION. Implémenter la pagination dans get_context.",
|
|
681
|
+
"example_output": "from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage\n\ndef get_context(self, request):\n context = super().get_context(request)\n posts = BlogPage.objects.live()\n paginator = Paginator(posts, 10)\n page = request.GET.get('page')\n try:\n posts = paginator.page(page)\n except PageNotAnInteger:\n posts = paginator.page(1)\n except EmptyPage:\n posts = paginator.page(paginator.num_pages)\n context['posts'] = posts\n return context",
|
|
682
|
+
"documentation": "Diviser une liste d'objets sur plusieurs pages. Django fournit la classe `Paginator` pour gérer cela facilement.",
|
|
683
|
+
"documentation_officielle": "Django fournit une classe Paginator pour gérer la pagination des données, permettant de diviser une liste d'objets sur plusieurs pages."
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
"terms": [
|
|
687
|
+
"search",
|
|
688
|
+
"recherche",
|
|
689
|
+
"search backend",
|
|
690
|
+
"elasticsearch"
|
|
691
|
+
],
|
|
692
|
+
"instruction": "INTENT DETECTED: SEARCH. Configurer la recherche Wagtail avec search_fields.",
|
|
693
|
+
"example_output": "from wagtail.search import index\n\nsearch_fields = Page.search_fields + [\n index.SearchField('body'),\n index.FilterField('date'),\n index.AutocompleteField('title'),\n]",
|
|
694
|
+
"documentation": "Wagtail intègre un moteur de recherche puissant (compatible Elasticsearch) pour indexer et rechercher dans les pages et images.",
|
|
695
|
+
"documentation_officielle": "Wagtail inclut un backend de recherche abstrait qui permet d'indexer et de rechercher des objets (pages, images, documents) en utilisant une API unifiée."
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
"terms": [
|
|
699
|
+
"annotation",
|
|
700
|
+
"aggregate",
|
|
701
|
+
"count",
|
|
702
|
+
"sum",
|
|
703
|
+
"avg"
|
|
704
|
+
],
|
|
705
|
+
"instruction": "INTENT DETECTED: AGGREGATION. Utiliser annotate() et aggregate() pour calculs.",
|
|
706
|
+
"example_output": "from django.db.models import Count, Avg\n\nauthors = Author.objects.annotate(\n article_count=Count('articles'),\n avg_views=Avg('articles__views')\n)",
|
|
707
|
+
"documentation": "Calculer des valeurs sur un ensemble d'objets (somme, moyenne, compte) directement en base de données.",
|
|
708
|
+
"documentation_officielle": "Django permet de générer des agrégats (statistiques) sur un QuerySet, comme compter, sommer ou faire la moyenne des valeurs des champs."
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"terms": [
|
|
712
|
+
"distinct",
|
|
713
|
+
"unique values",
|
|
714
|
+
"valeurs uniques"
|
|
715
|
+
],
|
|
716
|
+
"instruction": "INTENT DETECTED: DISTINCT. Utiliser distinct() pour éliminer les doublons.",
|
|
717
|
+
"example_output": "tags = Tag.objects.filter(articles__status='published').distinct()",
|
|
718
|
+
"documentation": "Élimine les doublons dans les résultats d'une requête.",
|
|
719
|
+
"documentation_officielle": "La méthode distinct() renvoie un nouveau QuerySet avec les résultats en double éliminés."
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
"terms": [
|
|
723
|
+
"exists",
|
|
724
|
+
"vérification existence"
|
|
725
|
+
],
|
|
726
|
+
"instruction": "INTENT DETECTED: EXISTS. Utiliser exists() pour vérifier l'existence efficacement.",
|
|
727
|
+
"example_output": "has_posts = BlogPage.objects.child_of(self).exists()",
|
|
728
|
+
"documentation": "Vérifie efficacement si au moins un objet correspond à la requête, sans récupérer les données.",
|
|
729
|
+
"documentation_officielle": "La méthode exists() renvoie True si le QuerySet contient des résultats, et False sinon. C'est la méthode la plus efficace pour vérifier l'existence."
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
"terms": [
|
|
733
|
+
"formulaire",
|
|
734
|
+
"form",
|
|
735
|
+
"saisie",
|
|
736
|
+
"input utilisateur",
|
|
737
|
+
"form page"
|
|
738
|
+
],
|
|
739
|
+
"instruction": "INTENT DETECTED: FORM. Créer un formulaire Django ou hériter de FormPage dans Wagtail.",
|
|
740
|
+
"example_output": "from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField\n\nclass ContactPage(AbstractEmailForm):\n intro = RichTextField(blank=True)\n thank_you_text = RichTextField(blank=True)\n \n content_panels = AbstractEmailForm.content_panels + [\n FieldPanel('intro'),\n InlinePanel('form_fields', label='Champs du formulaire'),\n FieldPanel('thank_you_text'),\n MultiFieldPanel([\n FieldPanel('to_address'),\n FieldPanel('from_address'),\n FieldPanel('subject'),\n ], 'Email'),\n ]",
|
|
741
|
+
"documentation": "Classe définissant un formulaire, ses champs et sa validation. Wagtail propose `FormPage` pour créer des formulaires administrables.",
|
|
742
|
+
"documentation_officielle": "La classe Form de Django décrit un formulaire, détermine comment il fonctionne et apparaît, et gère la validation des données."
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
"terms": [
|
|
746
|
+
"validation",
|
|
747
|
+
"validator",
|
|
748
|
+
"clean",
|
|
749
|
+
"contrainte formulaire"
|
|
750
|
+
],
|
|
751
|
+
"instruction": "INTENT DETECTED: FORM VALIDATION. Ajouter validation personnalisée avec clean() ou validators.",
|
|
752
|
+
"example_output": "from django.core.exceptions import ValidationError\n\ndef clean(self):\n cleaned_data = super().clean()\n start = cleaned_data.get('start_date')\n end = cleaned_data.get('end_date')\n if start and end and start > end:\n raise ValidationError('La date de fin doit être après la date de début')\n return cleaned_data",
|
|
753
|
+
"documentation": "Processus de vérification des données soumises. La méthode `clean()` permet une validation croisée entre plusieurs champs.",
|
|
754
|
+
"documentation_officielle": "La classe Form de Django décrit un formulaire, détermine comment il fonctionne et apparaît, et gère la validation des données."
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"terms": [
|
|
758
|
+
"modelform",
|
|
759
|
+
"form depuis modèle"
|
|
760
|
+
],
|
|
761
|
+
"instruction": "INTENT DETECTED: MODEL FORM. Créer un formulaire à partir d'un modèle avec ModelForm.",
|
|
762
|
+
"example_output": "from django import forms\n\nclass ArticleForm(forms.ModelForm):\n class Meta:\n model = Article\n fields = ['title', 'content', 'status']\n widgets = {\n 'content': forms.Textarea(attrs={'rows': 5}),\n }",
|
|
763
|
+
"documentation": "Un formulaire généré automatiquement à partir d'un modèle, mappant les champs du modèle aux champs du formulaire.",
|
|
764
|
+
"documentation_officielle": "ModelForm est une classe helper qui crée automatiquement une classe Form à partir d'un modèle Django, mappant les champs du modèle aux champs du formulaire."
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
"terms": [
|
|
768
|
+
"url",
|
|
769
|
+
"route",
|
|
770
|
+
"chemin",
|
|
771
|
+
"endpoint",
|
|
772
|
+
"path"
|
|
773
|
+
],
|
|
774
|
+
"instruction": "INTENT DETECTED: URL ROUTING. Définir les routes Django dans urls.py.",
|
|
775
|
+
"example_output": "from django.urls import path\nfrom . import views\n\nurlpatterns = [\n path('articles/', views.article_list, name='article_list'),\n path('articles/<slug:slug>/', views.article_detail, name='article_detail'),\n]",
|
|
776
|
+
"documentation": "Le système d'URL de Django mappe les URL demandées à des fonctions de vue (views) via des expressions (path ou re_path).",
|
|
777
|
+
"documentation_officielle": "Le dispatcher d'URL de Django associe les modèles d'URL demandés aux fonctions de vue (views) appropriées."
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"terms": [
|
|
781
|
+
"redirect",
|
|
782
|
+
"redirection",
|
|
783
|
+
"renvoi"
|
|
784
|
+
],
|
|
785
|
+
"instruction": "INTENT DETECTED: REDIRECT. Créer une redirection avec redirect() ou RedirectView.",
|
|
786
|
+
"example_output": "from django.shortcuts import redirect\n\ndef old_view(request):\n return redirect('new_view', permanent=True)",
|
|
787
|
+
"documentation": "Renvoyer une réponse HTTP demandant au navigateur d'aller à une autre URL.",
|
|
788
|
+
"documentation_officielle": "Une redirection renvoie une réponse HTTP spéciale qui demande au navigateur d'aller à une autre URL."
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
"terms": [
|
|
792
|
+
"api",
|
|
793
|
+
"json",
|
|
794
|
+
"headless",
|
|
795
|
+
"endpoint api",
|
|
796
|
+
"rest"
|
|
797
|
+
],
|
|
798
|
+
"instruction": "INTENT DETECTED: WAGTAIL API. Exposer des pages via l'API Wagtail avec api_fields.",
|
|
799
|
+
"example_output": "from wagtail.api import APIField\n\napi_fields = [\n APIField('subtitle'),\n APIField('author'),\n APIField('featured_image'),\n]",
|
|
800
|
+
"documentation": "Module permettant d'exposer le contenu Wagtail (Pages, Images, Documents) via une API REST JSON.",
|
|
801
|
+
"documentation_officielle": "Le module wagtail.api fournit une API publique en lecture seule pour accéder au contenu de votre site (pages, images, documents) au format JSON."
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
"terms": [
|
|
805
|
+
"serializer",
|
|
806
|
+
"sérialisation",
|
|
807
|
+
"drf",
|
|
808
|
+
"django rest framework"
|
|
809
|
+
],
|
|
810
|
+
"instruction": "INTENT DETECTED: DRF SERIALIZER. Créer un serializer Django REST Framework.",
|
|
811
|
+
"example_output": "from rest_framework import serializers\n\nclass ArticleSerializer(serializers.ModelSerializer):\n class Meta:\n model = Article\n fields = ['id', 'title', 'slug', 'content', 'published_date']",
|
|
812
|
+
"documentation": "Transforme des types de données complexes (QuerySets, instances) en types natifs Python (JSON) et inversement.",
|
|
813
|
+
"documentation_officielle": "Les sérialiseurs permettent de convertir des données complexes (comme les instances de modèles) en types de données natifs Python qui peuvent être facilement rendus en JSON ou XML."
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
"terms": [
|
|
817
|
+
"viewset",
|
|
818
|
+
"api view",
|
|
819
|
+
"vue api"
|
|
820
|
+
],
|
|
821
|
+
"instruction": "INTENT DETECTED: DRF VIEWSET. Créer un ViewSet pour exposer des endpoints CRUD.",
|
|
822
|
+
"example_output": "from rest_framework import viewsets\n\nclass ArticleViewSet(viewsets.ModelViewSet):\n queryset = Article.objects.all()\n serializer_class = ArticleSerializer",
|
|
823
|
+
"documentation": "Combine la logique de plusieurs vues liées (list, create, retrieve, update, destroy) en une seule classe.",
|
|
824
|
+
"documentation_officielle": "Les ViewSets permettent de combiner la logique d'un ensemble de vues associées (comme list, create, retrieve) dans une seule classe."
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
"terms": [
|
|
828
|
+
"signal",
|
|
829
|
+
"événement",
|
|
830
|
+
"post_save",
|
|
831
|
+
"pre_save",
|
|
832
|
+
"trigger"
|
|
833
|
+
],
|
|
834
|
+
"instruction": "INTENT DETECTED: DJANGO SIGNAL. Réagir aux événements modèle avec signals.",
|
|
835
|
+
"example_output": "from django.db.models.signals import post_save\nfrom django.dispatch import receiver\n\n@receiver(post_save, sender=Article)\ndef article_saved(sender, instance, created, **kwargs):\n if created:\n # Nouvelle création\n pass",
|
|
836
|
+
"documentation": "Système de dispatch permettant à des composants découplés d'être notifiés quand certaines actions se produisent (ex: post_save).",
|
|
837
|
+
"documentation_officielle": "Django inclut un distributeur de signaux qui permet aux applications découplées d'être notifiées quand des actions se produisent ailleurs dans le framework."
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
"terms": [
|
|
841
|
+
"hook",
|
|
842
|
+
"wagtail hook",
|
|
843
|
+
"register hook"
|
|
844
|
+
],
|
|
845
|
+
"instruction": "INTENT DETECTED: WAGTAIL HOOK. Utiliser les hooks Wagtail pour étendre le comportement.",
|
|
846
|
+
"example_output": "from wagtail import hooks\n\n@hooks.register('before_serve_page')\ndef set_custom_header(page, request, serve_args, serve_kwargs):\n # Logique custom\n pass",
|
|
847
|
+
"documentation": "Points d'entrée permettant d'exécuter du code à des moments précis du cycle de vie Wagtail ou de modifier l'interface admin.",
|
|
848
|
+
"documentation_officielle": "Les hooks sont un mécanisme permettant d'exécuter du code à certains points d'extension de Wagtail, par exemple pour modifier le menu admin ou le rendu des pages."
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
"terms": [
|
|
852
|
+
"admin hook",
|
|
853
|
+
"menu admin",
|
|
854
|
+
"customisation admin"
|
|
855
|
+
],
|
|
856
|
+
"instruction": "INTENT DETECTED: ADMIN HOOK. Ajouter des éléments au menu admin Wagtail.",
|
|
857
|
+
"example_output": "from wagtail import hooks\nfrom wagtail.admin.menu import MenuItem\n\n@hooks.register('register_admin_menu_item')\ndef register_reports_menu():\n return MenuItem(\n 'Rapports',\n '/admin/reports/',\n icon_name='doc-full',\n order=10000\n )",
|
|
858
|
+
"documentation": "Hooks spécifiques pour modifier le menu principal, ajouter des boutons ou des CSS/JS dans l'admin Wagtail.",
|
|
859
|
+
"documentation_officielle": "Les hooks d'administration permettent de personnaliser l'interface d'administration de Wagtail, par exemple en ajoutant des éléments de menu ou des fichiers CSS/JS."
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
"terms": [
|
|
863
|
+
"permission",
|
|
864
|
+
"autorisation",
|
|
865
|
+
"droits",
|
|
866
|
+
"access control"
|
|
867
|
+
],
|
|
868
|
+
"instruction": "INTENT DETECTED: PERMISSIONS. Gérer les permissions avec Meta.permissions ou decorators.",
|
|
869
|
+
"example_output": "class Meta:\n permissions = [\n ('can_publish_article', 'Peut publier des articles'),\n ]",
|
|
870
|
+
"documentation": "Système déterminant si un utilisateur peut effectuer une action (add, change, delete, view) sur un modèle.",
|
|
871
|
+
"documentation_officielle": "Le système d'authentification de Django gère à la fois l'authentification (vérification de l'identité) et l'autorisation (ce que l'utilisateur a le droit de faire)."
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
"terms": [
|
|
875
|
+
"group",
|
|
876
|
+
"groupe",
|
|
877
|
+
"utilisateur",
|
|
878
|
+
"rôle"
|
|
879
|
+
],
|
|
880
|
+
"instruction": "INTENT DETECTED: GROUPS. Créer des groupes d'utilisateurs avec permissions.",
|
|
881
|
+
"example_output": "from django.contrib.auth.models import Group, Permission\n\neditors_group = Group.objects.create(name='Éditeurs')\npermission = Permission.objects.get(codename='can_publish_article')\neditors_group.permissions.add(permission)",
|
|
882
|
+
"documentation": "Collections d'utilisateurs permettant d'attribuer des permissions en masse.",
|
|
883
|
+
"documentation_officielle": "Les groupes sont un moyen générique de classer les utilisateurs, afin que vous puissiez appliquer des permissions ou d'autres métadonnées à tous les membres du groupe."
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
"terms": [
|
|
887
|
+
"cache",
|
|
888
|
+
"performance",
|
|
889
|
+
"rapidité",
|
|
890
|
+
"optimisation"
|
|
891
|
+
],
|
|
892
|
+
"instruction": "INTENT DETECTED: CACHE. Mettre en cache avec decorators ou cache framework.",
|
|
893
|
+
"example_output": "from django.views.decorators.cache import cache_page\nfrom django.core.cache import cache\n\n@cache_page(60 * 15) # 15 minutes\ndef my_view(request):\n data = cache.get('my_data')\n if data is None:\n data = expensive_operation()\n cache.set('my_data', data, 60 * 60)\n return render(request, 'template.html', {'data': data})",
|
|
894
|
+
"documentation": "Stockage temporaire de données ou de pages entières pour améliorer les performances et réduire la charge de la base de données.",
|
|
895
|
+
"documentation_officielle": "Le système de cache de Django permet de stocker le résultat de calculs coûteux ou de requêtes afin de servir les requêtes futures plus rapidement."
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
"terms": [
|
|
899
|
+
"select_related",
|
|
900
|
+
"jointure",
|
|
901
|
+
"fk optimization"
|
|
902
|
+
],
|
|
903
|
+
"instruction": "INTENT DETECTED: SELECT RELATED. Optimiser les ForeignKey avec select_related().",
|
|
904
|
+
"example_output": "articles = Article.objects.select_related('author', 'category')",
|
|
905
|
+
"documentation": "Optimisation SQL effectuant une jointure (JOIN) pour récupérer les objets liés par ForeignKey en une seule requête.",
|
|
906
|
+
"documentation_officielle": "select_related renvoie un QuerySet qui suivra les relations de clé étrangère, sélectionnant les données liées supplémentaires lors de l'exécution de la requête."
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
"terms": [
|
|
910
|
+
"prefetch_related",
|
|
911
|
+
"m2m optimization",
|
|
912
|
+
"reverse fk"
|
|
913
|
+
],
|
|
914
|
+
"instruction": "INTENT DETECTED: PREFETCH RELATED. Optimiser M2M et reverse FK avec prefetch_related().",
|
|
915
|
+
"example_output": "from django.db.models import Prefetch\n\nauthors = Author.objects.prefetch_related(\n Prefetch('articles', queryset=Article.objects.filter(status='published'))\n)",
|
|
916
|
+
"documentation": "Optimisation SQL pour les relations ManyToMany ou Reverse ForeignKey, effectuant une requête séparée et liant les résultats en Python.",
|
|
917
|
+
"documentation_officielle": "prefetch_related effectue des recherches séparées pour chaque relation et effectue le 'joining' en Python. Il est utilisé pour les relations ManyToMany et ForeignKey inversées."
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
"terms": [
|
|
921
|
+
"only",
|
|
922
|
+
"defer",
|
|
923
|
+
"champs sélectifs"
|
|
924
|
+
],
|
|
925
|
+
"instruction": "INTENT DETECTED: FIELD SELECTION. Limiter les champs chargés avec only() ou defer().",
|
|
926
|
+
"example_output": "articles = Article.objects.only('id', 'title', 'slug')\n# ou\narticles = Article.objects.defer('content', 'metadata')",
|
|
927
|
+
"documentation": "`only()` et `defer()` permettent de ne charger qu'un sous-ensemble des champs d'un modèle pour optimiser la mémoire.",
|
|
928
|
+
"documentation_officielle": "La partie la plus importante d'un modèle – et la seule obligatoire – est la liste des champs de base de données qu'il définit. Les champs sont spécifiés par des attributs de classe."
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"terms": [
|
|
932
|
+
"bulk",
|
|
933
|
+
"bulk_create",
|
|
934
|
+
"bulk_update",
|
|
935
|
+
"masse"
|
|
936
|
+
],
|
|
937
|
+
"instruction": "INTENT DETECTED: BULK OPERATIONS. Créer/modifier en masse avec bulk_create() et bulk_update().",
|
|
938
|
+
"example_output": "Article.objects.bulk_create([\n Article(title='Article 1'),\n Article(title='Article 2'),\n])\n\nArticle.objects.bulk_update(articles_list, ['status', 'updated_at'])",
|
|
939
|
+
"documentation": "Méthodes pour créer ou mettre à jour de nombreux objets en une seule requête SQL, beaucoup plus rapide que des boucles."
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
"terms": [
|
|
943
|
+
"migration",
|
|
944
|
+
"schema",
|
|
945
|
+
"base de données",
|
|
946
|
+
"makemigrations",
|
|
947
|
+
"migrate"
|
|
948
|
+
],
|
|
949
|
+
"instruction": "INTENT DETECTED: MIGRATION. Générer et appliquer des migrations Django.",
|
|
950
|
+
"example_output": "# Créer migrations\npython manage.py makemigrations\n\n# Appliquer migrations\npython manage.py migrate\n\n# Migration personnalisée\npython manage.py makemigrations --empty myapp",
|
|
951
|
+
"documentation": "Fichiers décrivant les changements de schéma de base de données. Ils permettent de propager les modifications des modèles vers la DB.",
|
|
952
|
+
"documentation_officielle": "Les migrations sont la façon dont Django propage les changements que vous apportez à vos modèles (ajout d'un champ, suppression d'un modèle, etc.) dans le schéma de votre base de données."
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
"terms": [
|
|
956
|
+
"data migration",
|
|
957
|
+
"migration données",
|
|
958
|
+
"populate"
|
|
959
|
+
],
|
|
960
|
+
"instruction": "INTENT DETECTED: DATA MIGRATION. Créer une migration de données.",
|
|
961
|
+
"example_output": "from django.db import migrations\n\ndef populate_data(apps, schema_editor):\n Article = apps.get_model('blog', 'Article')\n Article.objects.create(title='Initial Article')\n\nclass Migration(migrations.Migration):\n dependencies = [('blog', '0001_initial')]\n operations = [migrations.RunPython(populate_data)]",
|
|
962
|
+
"documentation": "Migration spéciale exécutant du code Python pour manipuler les données existantes lors d'un changement de schéma.",
|
|
963
|
+
"documentation_officielle": "Les migrations de données permettent de modifier les données dans la base de données en même temps que le schéma, souvent pour adapter les données existantes à une nouvelle structure."
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
"terms": [
|
|
967
|
+
"settings",
|
|
968
|
+
"config",
|
|
969
|
+
"configuration",
|
|
970
|
+
"paramètres projet"
|
|
971
|
+
],
|
|
972
|
+
"instruction": "INTENT DETECTED: SETTINGS. Configurer le projet dans settings.py.",
|
|
973
|
+
"example_output": "# settings.py\nWAGTAIL_SITE_NAME = 'Mon Site'\nWAGTAILADMIN_BASE_URL = 'https://example.com'\n\nINSTALLED_APPS = [\n 'myapp',\n 'wagtail.contrib.forms',\n]\n\nMEDIA_URL = '/media/'\nMEDIA_ROOT = BASE_DIR / 'media'",
|
|
974
|
+
"documentation": "Fichier central de configuration de Django (BDD, apps installées, middleware, templates, etc.).",
|
|
975
|
+
"documentation_officielle": "Un fichier de paramètres Django contient toute la configuration de votre installation Django."
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
"terms": [
|
|
979
|
+
"middleware",
|
|
980
|
+
"intergiciel"
|
|
981
|
+
],
|
|
982
|
+
"instruction": "INTENT DETECTED: MIDDLEWARE. Ajouter ou créer un middleware.",
|
|
983
|
+
"example_output": "# settings.py\nMIDDLEWARE = [\n 'django.middleware.security.SecurityMiddleware',\n 'myapp.middleware.CustomMiddleware',\n]\n\n# middleware.py\nclass CustomMiddleware:\n def __init__(self, get_response):\n self.get_response = get_response\n \n def __call__(self, request):\n response = self.get_response(request)\n return response",
|
|
984
|
+
"documentation": "Couches de traitement s'exécutant à chaque requête/réponse, permettant d'altérer globalement les entrées ou sorties.",
|
|
985
|
+
"documentation_officielle": "Le middleware est un cadre de hooks dans le traitement des requêtes/réponses de Django. C'est un système de plugins léger et de bas niveau pour modifier globalement l'entrée ou la sortie de Django."
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
"terms": [
|
|
989
|
+
"environnement",
|
|
990
|
+
"env",
|
|
991
|
+
"variable environnement",
|
|
992
|
+
"dotenv"
|
|
993
|
+
],
|
|
994
|
+
"instruction": "INTENT DETECTED: ENVIRONMENT VARIABLES. Utiliser des variables d'environnement.",
|
|
995
|
+
"example_output": "import os\nfrom pathlib import Path\nimport environ\n\nenv = environ.Env()\nenviron.Env.read_env()\n\nSECRET_KEY = env('SECRET_KEY')\nDEBUG = env.bool('DEBUG', default=False)\nDATABASE_URL = env('DATABASE_URL')",
|
|
996
|
+
"documentation": "Bonne pratique consistant à séparer la configuration sensible (clés secrètes, DB passwords) du code source.",
|
|
997
|
+
"documentation_officielle": "Il est recommandé de séparer la configuration du code. L'utilisation de variables d'environnement permet de garder les secrets (comme SECRET_KEY) hors du code source."
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
"terms": [
|
|
1001
|
+
"authentification",
|
|
1002
|
+
"login",
|
|
1003
|
+
"connexion",
|
|
1004
|
+
"user"
|
|
1005
|
+
],
|
|
1006
|
+
"instruction": "INTENT DETECTED: AUTHENTICATION. Gérer l'authentification utilisateur.",
|
|
1007
|
+
"example_output": "from django.contrib.auth.decorators import login_required\nfrom django.contrib.auth import authenticate, login\n\n@login_required\ndef my_view(request):\n pass\n\ndef login_view(request):\n user = authenticate(username=username, password=password)\n if user:\n login(request, user)",
|
|
1008
|
+
"documentation": "Système gérant les comptes utilisateurs, les sessions, et la vérification des identités.",
|
|
1009
|
+
"documentation_officielle": "Django fournit un système d'authentification complet, gérant les comptes utilisateurs, les groupes, les permissions et les sessions basées sur les cookies."
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"terms": [
|
|
1013
|
+
"custom user",
|
|
1014
|
+
"utilisateur personnalisé",
|
|
1015
|
+
"user model"
|
|
1016
|
+
],
|
|
1017
|
+
"instruction": "INTENT DETECTED: CUSTOM USER MODEL. Créer un modèle utilisateur personnalisé.",
|
|
1018
|
+
"example_output": "from django.contrib.auth.models import AbstractUser\n\nclass CustomUser(AbstractUser):\n bio = models.TextField(blank=True)\n avatar = models.ImageField(upload_to='avatars/', blank=True)\n\n# settings.py\nAUTH_USER_MODEL = 'myapp.CustomUser'",
|
|
1019
|
+
"documentation": "Remplacement du modèle User par défaut de Django pour ajouter des champs spécifiques au projet.",
|
|
1020
|
+
"documentation_officielle": "Django permet de substituer un modèle d'utilisateur personnalisé au modèle User par défaut, ce qui permet d'utiliser une adresse email comme identifiant ou d'ajouter des champs spécifiques."
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
"terms": [
|
|
1024
|
+
"test",
|
|
1025
|
+
"unittest",
|
|
1026
|
+
"testing",
|
|
1027
|
+
"test case"
|
|
1028
|
+
],
|
|
1029
|
+
"instruction": "INTENT DETECTED: TESTING. Créer des tests unitaires Django/Wagtail.",
|
|
1030
|
+
"example_output": "from django.test import TestCase\nfrom wagtail.test.utils import WagtailPageTests\n\nclass ArticlePageTest(TestCase, WagtailPageTests):\n def test_can_create_article(self):\n article = ArticlePage(title='Test', slug='test')\n self.assertCanCreate(HomePage, article)",
|
|
1031
|
+
"documentation": "Pratique consistant à écrire du code pour vérifier que l'application fonctionne comme prévu et prévenir les régressions.",
|
|
1032
|
+
"documentation_officielle": "Les tests automatisés sont des routines qui vérifient le fonctionnement de votre code. Django fournit un framework de test basé sur le module unittest de Python."
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
"terms": [
|
|
1036
|
+
"factory",
|
|
1037
|
+
"fixture",
|
|
1038
|
+
"données test"
|
|
1039
|
+
],
|
|
1040
|
+
"instruction": "INTENT DETECTED: TEST FIXTURES. Créer des fixtures ou factories pour les tests.",
|
|
1041
|
+
"example_output": "import factory\nfrom factory.django import DjangoModelFactory\n\nclass ArticleFactory(DjangoModelFactory):\n class Meta:\n model = Article\n \n title = factory.Sequence(lambda n: f'Article {n}')\n slug = factory.LazyAttribute(lambda obj: slugify(obj.title))",
|
|
1042
|
+
"documentation": "Données de test pré-remplies ou générées dynamiquement (factories) pour mettre la base de données dans un état connu avant les tests.",
|
|
1043
|
+
"documentation_officielle": "Une fixture est une collection de données que Django peut charger dans la base de données. C'est utile pour charger des données de test initiales."
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
"terms": [
|
|
1047
|
+
"i18n",
|
|
1048
|
+
"traduction",
|
|
1049
|
+
"translation",
|
|
1050
|
+
"multilingue",
|
|
1051
|
+
"langue"
|
|
1052
|
+
],
|
|
1053
|
+
"instruction": "INTENT DETECTED: INTERNATIONALIZATION. Gérer les traductions avec i18n.",
|
|
1054
|
+
"example_output": "from django.utils.translation import gettext_lazy as _\n\nclass Article(models.Model):\n title = models.CharField(_('titre'), max_length=200)\n \n class Meta:\n verbose_name = _('article')\n verbose_name_plural = _('articles')",
|
|
1055
|
+
"documentation": "Processus de conception de l'application pour qu'elle puisse être adaptée à différentes langues et régions sans modifications techniques.",
|
|
1056
|
+
"documentation_officielle": "L'internationalisation (i18n) est le processus de conception d'une application logicielle afin qu'elle puisse être adaptée à diverses langues et régions sans modification technique."
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
"terms": [
|
|
1060
|
+
"wagtail localize",
|
|
1061
|
+
"traduction wagtail",
|
|
1062
|
+
"multilingual"
|
|
1063
|
+
],
|
|
1064
|
+
"instruction": "INTENT DETECTED: WAGTAIL LOCALIZE. Configurer wagtail-localize pour traductions de pages.",
|
|
1065
|
+
"example_output": "# settings.py\nINSTALLED_APPS += ['wagtail_localize']\n\n# models.py\nfrom wagtail_localize.fields import TranslatableField\n\nclass ArticlePage(Page):\n translatable_fields = [\n TranslatableField('title'),\n TranslatableField('body'),\n ]",
|
|
1066
|
+
"documentation": "Extension Wagtail facilitant la traduction de contenu avec synchronisation des arbres de pages et intégration d'outils de traduction.",
|
|
1067
|
+
"documentation_officielle": "Wagtail Localize est un plugin qui facilite la traduction du contenu Wagtail en intégrant des services de traduction et en synchronisant les arbres de pages."
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
"terms": [
|
|
1071
|
+
"workflow",
|
|
1072
|
+
"flux travail",
|
|
1073
|
+
"modération",
|
|
1074
|
+
"approbation"
|
|
1075
|
+
],
|
|
1076
|
+
"instruction": "INTENT DETECTED: WORKFLOW. Configurer des workflows de modération Wagtail.",
|
|
1077
|
+
"example_output": "from wagtail.models import WorkflowState\n\nclass ArticlePage(Page):\n def get_workflow(self):\n return Workflow.objects.get(name='Article Approval')",
|
|
1078
|
+
"documentation": "Système permettant de définir des étapes de validation (ex: rédaction -> révision -> publication) avant la mise en ligne.",
|
|
1079
|
+
"documentation_officielle": "Les workflows permettent de définir des processus de modération personnalisés pour les pages, impliquant plusieurs étapes d'approbation avant la publication."
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
"terms": [
|
|
1083
|
+
"révision",
|
|
1084
|
+
"version",
|
|
1085
|
+
"historique"
|
|
1086
|
+
],
|
|
1087
|
+
"instruction": "INTENT DETECTED: REVISIONS. Gérer les révisions de page Wagtail.",
|
|
1088
|
+
"example_output": "# Récupérer les révisions\nrevisions = page.revisions.all()\n\n# Créer une révision\npage.save_revision()\n\n# Revenir à une révision\nrevision = page.revisions.first()\nrevision.publish()",
|
|
1089
|
+
"documentation": "Wagtail conserve un historique des modifications de chaque page, permettant de comparer ou de revenir à une version antérieure.",
|
|
1090
|
+
"documentation_officielle": "Wagtail enregistre une copie du contenu de la page (une révision) chaque fois que vous l'enregistrez ou la publiez, permettant de revenir à des états antérieurs."
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
"terms": [
|
|
1094
|
+
"modeladmin",
|
|
1095
|
+
"admin personnalisé",
|
|
1096
|
+
"listing admin"
|
|
1097
|
+
],
|
|
1098
|
+
"instruction": "INTENT DETECTED: MODEL ADMIN. Créer une interface admin personnalisée avec ModelAdmin.",
|
|
1099
|
+
"example_output": "from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register\n\nclass ArticleAdmin(ModelAdmin):\n model = Article\n menu_label = 'Articles'\n menu_icon = 'doc-full'\n list_display = ('title', 'status', 'created_at')\n list_filter = ('status', 'created_at')\n search_fields = ('title', 'content')\n\nmodeladmin_register(ArticleAdmin)",
|
|
1100
|
+
"documentation": "Module `wagtail.contrib.modeladmin` permettant de créer des interfaces CRUD pour n'importe quel modèle Django dans l'admin Wagtail.",
|
|
1101
|
+
"documentation_officielle": "ModelAdmin (désormais remplacé par les Snippets améliorés dans Wagtail récent) permet de créer une interface d'administration complète pour n'importe quel modèle Django."
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
"terms": [
|
|
1105
|
+
"viewset wagtail",
|
|
1106
|
+
"custom listing"
|
|
1107
|
+
],
|
|
1108
|
+
"instruction": "INTENT DETECTED: SNIPPET VIEWSET. Créer un viewset personnalisé pour snippets.",
|
|
1109
|
+
"example_output": "from wagtail.snippets.views.snippets import SnippetViewSet\nfrom wagtail.snippets.models import register_snippet\n\nclass AuthorViewSet(SnippetViewSet):\n model = Author\n icon = 'user'\n list_display = ['name', 'email']\n search_fields = ['name']\n\nregister_snippet(AuthorViewSet)",
|
|
1110
|
+
"documentation": "Classe permettant de personnaliser l'affichage et la gestion des snippets dans l'admin, unifiant la gestion des modèles.",
|
|
1111
|
+
"documentation_officielle": "Les snippets sont des morceaux de contenu réutilisables (comme des auteurs ou des catégories) qui n'ont pas besoin de faire partie de l'arborescence hiérarchique des pages."
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
"terms": [
|
|
1115
|
+
"csrf",
|
|
1116
|
+
"sécurité",
|
|
1117
|
+
"protection"
|
|
1118
|
+
],
|
|
1119
|
+
"instruction": "INTENT DETECTED: CSRF PROTECTION. Gérer la protection CSRF dans les formulaires.",
|
|
1120
|
+
"example_output": "{% csrf_token %}\n\n# Dans une vue\nfrom django.views.decorators.csrf import csrf_exempt\n\n@csrf_exempt\ndef my_api_view(request):\n pass",
|
|
1121
|
+
"documentation": "Protection contre les attaques Cross Site Request Forgery. Django exige un jeton CSRF pour toute requête POST provenant d'un formulaire.",
|
|
1122
|
+
"documentation_officielle": "Le middleware CSRF de Django protège contre les attaques de falsification de requête inter-sites (Cross Site Request Forgery) en vérifiant un jeton secret dans chaque requête POST."
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
"terms": [
|
|
1126
|
+
"xss",
|
|
1127
|
+
"injection",
|
|
1128
|
+
"sanitize"
|
|
1129
|
+
],
|
|
1130
|
+
"instruction": "INTENT DETECTED: XSS PROTECTION. Protéger contre les injections XSS.",
|
|
1131
|
+
"example_output": "from django.utils.html import escape\n\n# Dans template\n{{ user_input|escape }}\n\n# Dans code\nescaped = escape(user_input)",
|
|
1132
|
+
"documentation": "Protection contre le Cross Site Scripting. Les templates Django échappent automatiquement les variables, sauf si marquées comme sûres.",
|
|
1133
|
+
"documentation_officielle": "Les templates Django protègent contre les attaques XSS (Cross Site Scripting) en échappant automatiquement les caractères dangereux dans les variables."
|
|
1134
|
+
},
|
|
1135
|
+
{
|
|
1136
|
+
"terms": [
|
|
1137
|
+
"collectstatic",
|
|
1138
|
+
"static files",
|
|
1139
|
+
"fichiers statiques"
|
|
1140
|
+
],
|
|
1141
|
+
"instruction": "INTENT DETECTED: STATIC FILES. Configurer et collecter les fichiers statiques.",
|
|
1142
|
+
"example_output": "# settings.py\nSTATIC_URL = '/static/'\nSTATIC_ROOT = BASE_DIR / 'staticfiles'\nSTATICFILES_DIRS = [BASE_DIR / 'static']\n\n# Commande\npython manage.py collectstatic --noinput",
|
|
1143
|
+
"documentation": "Fichiers (CSS, JS, images) servis tels quels. En production, `collectstatic` les rassemble en un seul endroit pour être servis efficacement.",
|
|
1144
|
+
"documentation_officielle": "Les fichiers statiques sont des fichiers qui ne changent pas dynamiquement (CSS, JavaScript, images). Django fournit django.contrib.staticfiles pour les gérer."
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
"terms": [
|
|
1148
|
+
"wsgi",
|
|
1149
|
+
"asgi",
|
|
1150
|
+
"gunicorn",
|
|
1151
|
+
"production"
|
|
1152
|
+
],
|
|
1153
|
+
"instruction": "INTENT DETECTED: DEPLOYMENT CONFIG. Configurer le déploiement production.",
|
|
1154
|
+
"example_output": "# gunicorn config\ngunicorn myproject.wsgi:application --bind 0.0.0.0:8000\n\n# settings.py production\nDEBUG = False\nALLOWED_HOSTS = ['example.com']\nSECURE_SSL_REDIRECT = True",
|
|
1155
|
+
"documentation": "Configuration nécessaire pour exécuter Django dans un environnement de production (WSGI/ASGI, serveur web, sécurité).",
|
|
1156
|
+
"documentation_officielle": "Le déploiement de Django nécessite de configurer un serveur WSGI (comme Gunicorn), un serveur web (Nginx), et de s'assurer que les paramètres de sécurité (DEBUG=False) sont corrects."
|
|
1157
|
+
}
|
|
1158
|
+
]
|