From 15cb6d815afe4383631459579d209e0036cb64af Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Wed, 2 Apr 2025 20:03:18 +0200 Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration=20de=20la=20g=C3=A9n=C3=A9ric?= =?UTF-8?q?it=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On créé une classe singleton pour les variables de configuration See #328 --- README.md | 2 + src/agenda_culturel/admin.py | 5 + .../locale/fr/LC_MESSAGES/django.po | 729 +++++++++--------- .../migrations/0161_siteconfiguration.py | 102 +++ src/agenda_culturel/models.py | 90 ++- src/agenda_culturel/settings/base.py | 3 + .../templates/agenda_culturel/page.html | 42 +- .../templates/agenda_culturel/statistics.html | 6 +- src/agenda_culturel/views.py | 3 +- src/requirements.txt | 1 + 10 files changed, 609 insertions(+), 374 deletions(-) create mode 100644 src/agenda_culturel/migrations/0161_siteconfiguration.py diff --git a/README.md b/README.md index 6241ca4..1be1f1f 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ On peut aussi peupler les positions de référence qui serviront aux recherches * ```make create-reference-locations``` +Une fois l'installation réussie, la configuration du site est possible en allant modifier l'objet "Configuration du site" dans l'administration de django. + ## Utilisation d'un proxy socket On peut activer à la main (pour l'instant) un proxy type socket pour l'import d'événements. diff --git a/src/agenda_culturel/admin.py b/src/agenda_culturel/admin.py index 9aa7044..d857f30 100644 --- a/src/agenda_culturel/admin.py +++ b/src/agenda_culturel/admin.py @@ -4,6 +4,8 @@ from django_better_admin_arrayfield.admin.mixins import DynamicArrayMixin from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget from django_better_admin_arrayfield.models.fields import DynamicArrayField +from solo.admin import SingletonModelAdmin + from .models import ( BatchImportation, Category, @@ -17,8 +19,11 @@ from .models import ( StaticContent, Tag, UserProfile, + SiteConfiguration, ) +admin.site.register(SiteConfiguration, SingletonModelAdmin) + admin.site.register(Category) admin.site.register(Tag) admin.site.register(StaticContent) diff --git a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po index 8c64f16..fc354c8 100644 --- a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po +++ b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: agenda_culturel\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-15 19:10+0100\n" +"POT-Creation-Date: 2025-04-02 19:41+0200\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n" "Last-Translator: Jean-Marie Favreau \n" "Language-Team: Jean-Marie Favreau \n" @@ -142,12 +142,12 @@ msgstr "dernier créé d'abord" msgid "Imported from" msgstr "Importé depuis" -#: agenda_culturel/filters.py:470 agenda_culturel/models.py:794 -#: agenda_culturel/models.py:2824 +#: agenda_culturel/filters.py:470 agenda_culturel/models.py:839 +#: agenda_culturel/models.py:2947 msgid "Status" msgstr "Status" -#: agenda_culturel/filters.py:471 agenda_culturel/models.py:2560 +#: agenda_culturel/filters.py:471 agenda_culturel/models.py:2712 msgid "Closed" msgstr "Fermé" @@ -156,7 +156,7 @@ msgid "Open" msgstr "Ouvert" #: agenda_culturel/filters.py:475 agenda_culturel/filters.py:476 -#: agenda_culturel/models.py:2554 +#: agenda_culturel/models.py:2706 msgid "Spam" msgstr "Spam" @@ -164,7 +164,7 @@ msgstr "Spam" msgid "Non spam" msgstr "Non spam" -#: agenda_culturel/filters.py:481 agenda_culturel/models.py:2575 +#: agenda_culturel/filters.py:481 agenda_culturel/models.py:2727 msgid "Type" msgstr "Type" @@ -195,11 +195,11 @@ msgstr "" msgid "Your email" msgstr "Votre adresse email" -#: agenda_culturel/forms.py:166 agenda_culturel/models.py:2542 +#: agenda_culturel/forms.py:166 agenda_culturel/models.py:2694 msgid "Your email address" msgstr "Votre adresse email" -#: agenda_culturel/forms.py:172 agenda_culturel/models.py:2567 +#: agenda_culturel/forms.py:172 agenda_culturel/models.py:2719 msgid "Comments" msgstr "Commentaires" @@ -214,28 +214,28 @@ msgstr "" msgid "Receive notification of publication or leave a message for moderation" msgstr "Être notifié de la publication ou laisser un message à la modération" -#: agenda_culturel/forms.py:206 agenda_culturel/models.py:235 -#: agenda_culturel/models.py:802 agenda_culturel/models.py:2718 -#: agenda_culturel/models.py:2859 +#: agenda_culturel/forms.py:206 agenda_culturel/models.py:280 +#: agenda_culturel/models.py:847 agenda_culturel/models.py:2871 +#: agenda_culturel/models.py:2982 msgid "Category" msgstr "Catégorie" #: agenda_culturel/forms.py:212 agenda_culturel/forms.py:245 -#: agenda_culturel/forms.py:288 agenda_culturel/forms.py:468 -#: agenda_culturel/models.py:288 agenda_culturel/models.py:919 +#: agenda_culturel/forms.py:288 agenda_culturel/forms.py:472 +#: agenda_culturel/models.py:333 agenda_culturel/models.py:964 msgid "Tags" msgstr "Étiquettes" -#: agenda_culturel/forms.py:220 agenda_culturel/forms.py:631 -#: agenda_culturel/models.py:1048 +#: agenda_culturel/forms.py:220 agenda_culturel/forms.py:637 +#: agenda_culturel/models.py:1094 msgid "Event" msgstr "Événement" -#: agenda_culturel/forms.py:274 agenda_culturel/forms.py:474 +#: agenda_culturel/forms.py:274 agenda_culturel/forms.py:478 msgid "New tags" msgstr "Nouvelles étiquettes" -#: agenda_culturel/forms.py:276 agenda_culturel/forms.py:476 +#: agenda_culturel/forms.py:276 agenda_culturel/forms.py:480 msgid "" "Create new labels (sparingly). Note: by starting your tag with the " "characters “TW:”, youll create a “trigger warning” tag, and the associated " @@ -246,141 +246,142 @@ msgstr "" "étiquette “trigger warning”, et les événements associés seront annoncés " "comme tels." -#: agenda_culturel/forms.py:346 +#: agenda_culturel/forms.py:348 msgid "Main fields" msgstr "Champs principaux" -#: agenda_culturel/forms.py:349 +#: agenda_culturel/forms.py:351 msgid "Start of event" msgstr "Début de l'événement" -#: agenda_culturel/forms.py:353 +#: agenda_culturel/forms.py:355 msgid "End of event" msgstr "Fin de l'événement" -#: agenda_culturel/forms.py:359 +#: agenda_culturel/forms.py:361 msgid "This is a recurring event" msgstr "Cet événement est récurrent" -#: agenda_culturel/forms.py:371 +#: agenda_culturel/forms.py:373 msgid "Details" msgstr "Détails" -#: agenda_culturel/forms.py:376 agenda_culturel/models.py:831 -#: agenda_culturel/models.py:2693 +#: agenda_culturel/forms.py:378 agenda_culturel/models.py:876 +#: agenda_culturel/models.py:2846 msgid "Location" msgstr "Localisation" -#: agenda_culturel/forms.py:381 agenda_culturel/models.py:875 +#: agenda_culturel/forms.py:383 agenda_culturel/models.py:86 +#: agenda_culturel/models.py:920 msgid "Illustration" msgstr "Illustration" -#: agenda_culturel/forms.py:385 +#: agenda_culturel/forms.py:387 msgid "URLs" msgstr "URLs" -#: agenda_culturel/forms.py:389 agenda_culturel/forms.py:396 +#: agenda_culturel/forms.py:391 agenda_culturel/forms.py:398 msgid "Meta information" msgstr "Méta-informations" -#: agenda_culturel/forms.py:413 +#: agenda_culturel/forms.py:415 msgid "The end date must be after the start date." msgstr "La date de fin doit être après la date de début." -#: agenda_culturel/forms.py:429 +#: agenda_culturel/forms.py:431 msgid "The end time cannot be earlier than the start time." msgstr "L'heure de fin ne peut pas être avant l'heure de début." -#: agenda_culturel/forms.py:469 +#: agenda_culturel/forms.py:473 msgid "Select tags from existing ones." msgstr "Sélectionner des étiquettes depuis celles existantes." -#: agenda_culturel/forms.py:528 +#: agenda_culturel/forms.py:534 msgid "JSON in the format expected for the import." msgstr "JSON dans le format attendu pour l'import" -#: agenda_culturel/forms.py:550 +#: agenda_culturel/forms.py:556 msgid " (locally modified version)" msgstr " (version modifiée localement)" -#: agenda_culturel/forms.py:554 +#: agenda_culturel/forms.py:560 msgid " (synchronized on import version)" msgstr " (version synchronisée sur l'import)" -#: agenda_culturel/forms.py:558 +#: agenda_culturel/forms.py:564 msgid "Select {} as representative version." msgstr "Sélectionner {} comme version représentative" -#: agenda_culturel/forms.py:568 +#: agenda_culturel/forms.py:574 msgid "Update {} using some fields from other versions (interactive mode)." msgstr "" "Mettre à jour {} en utilisant quelques champs des autres versions (mode " "interactif)." -#: agenda_culturel/forms.py:575 +#: agenda_culturel/forms.py:581 msgid " Warning: a version is already locally modified." msgstr " Attention: une version a déjà été modifiée localement." -#: agenda_culturel/forms.py:582 +#: agenda_culturel/forms.py:588 msgid "Create a new version by merging (interactive mode)." msgstr "Créer une nouvelle version par fusion (mode interactif)." -#: agenda_culturel/forms.py:590 +#: agenda_culturel/forms.py:596 msgid "Make {} independent." msgstr "Rendre {} indépendant." -#: agenda_culturel/forms.py:593 +#: agenda_culturel/forms.py:599 msgid "Make all versions independent." msgstr "Rendre toutes les versions indépendantes." -#: agenda_culturel/forms.py:665 agenda_culturel/forms.py:678 +#: agenda_culturel/forms.py:671 agenda_culturel/forms.py:684 msgid "Value of version {}" msgstr "Valeur de la version {}" -#: agenda_culturel/forms.py:670 +#: agenda_culturel/forms.py:676 msgid "Value of the selected version" msgstr "Valeur de la version sélectionnée" -#: agenda_culturel/forms.py:840 +#: agenda_culturel/forms.py:846 msgid "Apply category {} to the event {}" msgstr "Appliquer la catégorie {} à l'événement {}" -#: agenda_culturel/forms.py:857 agenda_culturel/models.py:619 -#: agenda_culturel/models.py:2911 +#: agenda_culturel/forms.py:863 agenda_culturel/models.py:664 +#: agenda_culturel/models.py:3034 msgid "Place" msgstr "Lieu" -#: agenda_culturel/forms.py:859 +#: agenda_culturel/forms.py:865 msgid "Create a missing place" msgstr "Créer un lieu manquant" -#: agenda_culturel/forms.py:869 +#: agenda_culturel/forms.py:875 msgid "Add \"{}\" to the aliases of the place" msgstr "Ajouter « {} » aux alias du lieu" -#: agenda_culturel/forms.py:898 +#: agenda_culturel/forms.py:904 msgid "On saving, use aliases to detect all matching events with missing place" msgstr "" "Lors de l'enregistrement, utiliser des alias pour détecter tous les " "événements correspondants dont la place est manquante." -#: agenda_culturel/forms.py:911 +#: agenda_culturel/forms.py:917 msgid "Header" msgstr "Entête" -#: agenda_culturel/forms.py:914 agenda_culturel/models.py:581 +#: agenda_culturel/forms.py:920 agenda_culturel/models.py:626 msgid "Address" msgstr "Adresse" -#: agenda_culturel/forms.py:920 +#: agenda_culturel/forms.py:926 msgid "Meta" msgstr "Méta" -#: agenda_culturel/forms.py:923 +#: agenda_culturel/forms.py:929 msgid "Information" msgstr "Informations" -#: agenda_culturel/forms.py:975 +#: agenda_culturel/forms.py:981 msgid "Add a comment" msgstr "Ajouter un commentaire" @@ -413,31 +414,63 @@ msgstr "" "la page n'était pas encore peuplée des événements, le temps de chargement a " "sans doute été trop court" -#: agenda_culturel/models.py:70 +#: agenda_culturel/models.py:62 msgid "mean" msgstr "moyenne" -#: agenda_culturel/models.py:71 +#: agenda_culturel/models.py:62 msgid "median" msgstr "médiane" -#: agenda_culturel/models.py:72 +#: agenda_culturel/models.py:62 msgid "maximum" msgstr "maximum" -#: agenda_culturel/models.py:73 +#: agenda_culturel/models.py:62 msgid "minimum" msgstr "minimum" -#: agenda_culturel/models.py:74 +#: agenda_culturel/models.py:62 msgid "stdev" msgstr "écart-type" -#: agenda_culturel/models.py:86 +#: agenda_culturel/models.py:66 +msgid "Site name" +msgstr "Nom du site" + +#: agenda_culturel/models.py:69 +msgid "Site description" +msgstr "Description du site" + +#: agenda_culturel/models.py:73 +msgid "Keywords in html header" +msgstr "Mots-clés dans l'entête html" + +#: agenda_culturel/models.py:76 +msgid "Description in html header" +msgstr "Description dans l'entête html" + +#: agenda_culturel/models.py:79 +msgid "Google site verification value" +msgstr "Valeur de vérification de site Google" + +#: agenda_culturel/models.py:82 +msgid "Microsoft (bing) site verification value" +msgstr "Valeur de vérification de site Microsoft (bing)" + +#: agenda_culturel/models.py:92 +msgid "Illustration (development version)" +msgstr "Illustration (version de développement)" + +#: agenda_culturel/models.py:117 agenda_culturel/models.py:120 +msgid "Site Configuration" +msgstr "Configuration du site" + +#: agenda_culturel/models.py:131 msgid "Expert moderation user" msgstr "Utilisateur expert en modération" -#: agenda_culturel/models.py:88 +#: agenda_culturel/models.py:133 msgid "" "This user is an expert in moderation, and the interface features additional " "functionalities." @@ -445,102 +478,102 @@ msgstr "" "Cet utilisateur est un expert en modération, et l'interface comporte des " "fonctionnalités additionnelles." -#: agenda_culturel/models.py:94 agenda_culturel/models.py:98 +#: agenda_culturel/models.py:139 agenda_culturel/models.py:143 msgid "User profile" msgstr "" -#: agenda_culturel/models.py:95 +#: agenda_culturel/models.py:140 msgid "User profiles" msgstr "" -#: agenda_culturel/models.py:118 agenda_culturel/models.py:165 -#: agenda_culturel/models.py:244 agenda_culturel/models.py:538 -#: agenda_culturel/models.py:579 agenda_culturel/models.py:685 -#: agenda_culturel/models.py:2534 agenda_culturel/models.py:2643 +#: agenda_culturel/models.py:163 agenda_culturel/models.py:210 +#: agenda_culturel/models.py:289 agenda_culturel/models.py:583 +#: agenda_culturel/models.py:624 agenda_culturel/models.py:730 +#: agenda_culturel/models.py:2686 agenda_culturel/models.py:2796 msgid "Name" msgstr "Nom" -#: agenda_culturel/models.py:119 agenda_culturel/models.py:165 +#: agenda_culturel/models.py:164 agenda_culturel/models.py:210 msgid "Category name" msgstr "Nom de la catégorie" -#: agenda_culturel/models.py:124 +#: agenda_culturel/models.py:169 msgid "Content" msgstr "Contenu" -#: agenda_culturel/models.py:125 +#: agenda_culturel/models.py:170 msgid "Text as shown to the visitors" msgstr "Texte tel que présenté aux visiteureuses" -#: agenda_culturel/models.py:129 +#: agenda_culturel/models.py:174 msgid "URL path" msgstr "Chemin URL" -#: agenda_culturel/models.py:130 +#: agenda_culturel/models.py:175 msgid "URL path where the content is included." msgstr "Chemin URL où le contenu est présent." -#: agenda_culturel/models.py:134 +#: agenda_culturel/models.py:179 msgid "Static content" msgstr "Contenu statique" -#: agenda_culturel/models.py:135 +#: agenda_culturel/models.py:180 msgid "Static contents" msgstr "Contenus statiques" -#: agenda_culturel/models.py:171 +#: agenda_culturel/models.py:216 msgid "Color" msgstr "Couleur" -#: agenda_culturel/models.py:172 +#: agenda_culturel/models.py:217 msgid "Color used as background for the category" msgstr "Couleur utilisée comme fond de la catégorie" -#: agenda_culturel/models.py:178 +#: agenda_culturel/models.py:223 msgid "Pictogram" msgstr "Pictogramme" -#: agenda_culturel/models.py:179 +#: agenda_culturel/models.py:224 msgid "Pictogram of the category (svg format)" msgstr "Pictogramme de la catégorie (format svg)" -#: agenda_culturel/models.py:186 +#: agenda_culturel/models.py:231 msgid "Position for ordering categories" msgstr "Position pour ordonner les catégories" -#: agenda_culturel/models.py:236 +#: agenda_culturel/models.py:281 msgid "Categories" msgstr "Catégories" -#: agenda_culturel/models.py:245 +#: agenda_culturel/models.py:290 msgid "Tag name" msgstr "Nom de l'étiquette" -#: agenda_culturel/models.py:251 agenda_culturel/models.py:602 -#: agenda_culturel/models.py:701 agenda_culturel/models.py:858 +#: agenda_culturel/models.py:296 agenda_culturel/models.py:647 +#: agenda_culturel/models.py:746 agenda_culturel/models.py:903 msgid "Description" msgstr "Description" -#: agenda_culturel/models.py:252 +#: agenda_culturel/models.py:297 msgid "Description of the tag" msgstr "Description de l'étiquette" -#: agenda_culturel/models.py:258 agenda_culturel/models.py:2501 -#: agenda_culturel/models.py:2548 +#: agenda_culturel/models.py:303 agenda_culturel/models.py:2653 +#: agenda_culturel/models.py:2700 msgid "Message" msgstr "Message" -#: agenda_culturel/models.py:260 +#: agenda_culturel/models.py:305 msgid "Message displayed to the user on each event associated with this tag." msgstr "" "Message affiché à l'utilisateur sur chaque événement associé à cette " "étiquette." -#: agenda_culturel/models.py:267 +#: agenda_culturel/models.py:312 msgid "Principal" msgstr "Principal" -#: agenda_culturel/models.py:269 +#: agenda_culturel/models.py:314 msgid "" "This tag is highlighted as a main tag for visitors, particularly in the " "filter." @@ -548,91 +581,91 @@ msgstr "" "Cette étiquette est mise en avant comme étiquette principale pour les " "visiteurs, en particulier dans le filtre." -#: agenda_culturel/models.py:275 +#: agenda_culturel/models.py:320 msgid "In excluded suggestions" msgstr "Dans les suggestions d'exclusion" -#: agenda_culturel/models.py:276 +#: agenda_culturel/models.py:321 msgid "This tag will be part of the excluded suggestions." msgstr "Cette étiquette fera partie des suggestions d'exclusion." -#: agenda_culturel/models.py:281 +#: agenda_culturel/models.py:326 msgid "In included suggestions" msgstr "Dans les suggestions d'inclusion." -#: agenda_culturel/models.py:282 +#: agenda_culturel/models.py:327 msgid "This tag will be part of the included suggestions." msgstr "Cette étiquette fera partie des suggestions d'inclusion." -#: agenda_culturel/models.py:287 +#: agenda_culturel/models.py:332 msgid "Tag" msgstr "Étiquette" -#: agenda_culturel/models.py:376 +#: agenda_culturel/models.py:421 msgid "Suggestions" msgstr "Suggestions" -#: agenda_culturel/models.py:377 +#: agenda_culturel/models.py:422 msgid "Others" msgstr "Autres" -#: agenda_culturel/models.py:390 +#: agenda_culturel/models.py:435 msgid "Representative event" msgstr "Événement représentatif" -#: agenda_culturel/models.py:392 +#: agenda_culturel/models.py:437 msgid "This event is the representative event of the duplicated events group" msgstr "" "Cet événement est l'événement représentatif du groupe d'événements dupliqués." -#: agenda_culturel/models.py:400 agenda_culturel/models.py:401 +#: agenda_culturel/models.py:445 agenda_culturel/models.py:446 msgid "Duplicated events" msgstr "Événements dupliqués" -#: agenda_culturel/models.py:539 +#: agenda_culturel/models.py:584 msgid "Name of the location" msgstr "Nom de la position" -#: agenda_culturel/models.py:550 +#: agenda_culturel/models.py:595 msgid "Main" msgstr "Principale" -#: agenda_culturel/models.py:552 +#: agenda_culturel/models.py:597 msgid "This location is one of the main locations (shown first higher values)." msgstr "" "Cette position est une position principale (affichage en premier des plus " "grandes valeurs)." -#: agenda_culturel/models.py:557 +#: agenda_culturel/models.py:602 msgid "Suggested distance (km)" msgstr "" -#: agenda_culturel/models.py:559 +#: agenda_culturel/models.py:604 msgid "" "If this distance is given, this location is part of the suggested filters." msgstr "" -#: agenda_culturel/models.py:568 +#: agenda_culturel/models.py:613 msgid "Reference location" msgstr "Position de référence" -#: agenda_culturel/models.py:569 +#: agenda_culturel/models.py:614 msgid "Reference locations" msgstr "Positions de référence" -#: agenda_culturel/models.py:579 +#: agenda_culturel/models.py:624 msgid "Name of the place" msgstr "Nom du lieu" -#: agenda_culturel/models.py:582 +#: agenda_culturel/models.py:627 msgid "Address of this place (without city name)" msgstr "Adresse de ce lieu (sans le nom de la ville)" -#: agenda_culturel/models.py:587 +#: agenda_culturel/models.py:632 msgid "Postcode" msgstr "Code postal" -#: agenda_culturel/models.py:589 +#: agenda_culturel/models.py:634 msgid "" "The post code is not displayed, but makes it easier to find an address when " "you enter it." @@ -640,23 +673,23 @@ msgstr "" "Le code postal ne sera pas affiché, mais facilite la recherche d'adresse au " "moment de la saisie." -#: agenda_culturel/models.py:594 +#: agenda_culturel/models.py:639 msgid "City" msgstr "Ville" -#: agenda_culturel/models.py:594 +#: agenda_culturel/models.py:639 msgid "City name" msgstr "Nom de la ville" -#: agenda_culturel/models.py:603 +#: agenda_culturel/models.py:648 msgid "Description of the place, including accessibility." msgstr "Description du lieu, inclus l'accessibilité." -#: agenda_culturel/models.py:610 +#: agenda_culturel/models.py:655 msgid "Alternative names" msgstr "Noms alternatifs" -#: agenda_culturel/models.py:612 +#: agenda_culturel/models.py:657 msgid "" "Alternative names or addresses used to match a place with the free-form " "location of an event." @@ -664,31 +697,31 @@ msgstr "" "Noms et adresses alternatives qui seront utilisées pour associer une adresse " "avec la localisation en forme libre d'un événement" -#: agenda_culturel/models.py:620 +#: agenda_culturel/models.py:665 msgid "Places" msgstr "Lieux" -#: agenda_culturel/models.py:686 +#: agenda_culturel/models.py:731 msgid "Organisation name" msgstr "Nom de l'organisme" -#: agenda_culturel/models.py:693 +#: agenda_culturel/models.py:738 msgid "Website" msgstr "Site internet" -#: agenda_culturel/models.py:694 +#: agenda_culturel/models.py:739 msgid "Website of the organisation" msgstr "Site internet de l'organisme" -#: agenda_culturel/models.py:702 +#: agenda_culturel/models.py:747 msgid "Description of the organisation." msgstr "Description de l'organisme" -#: agenda_culturel/models.py:709 +#: agenda_culturel/models.py:754 msgid "Principal place" msgstr "Lieu principal" -#: agenda_culturel/models.py:711 +#: agenda_culturel/models.py:756 msgid "" "Place mainly associated with this organizer. Mainly used if there is a " "similarity in the name, to avoid redundant displays." @@ -696,75 +729,75 @@ msgstr "" "Lieu principalement associé à cet organisateur. Principalement utilisé s'il " "y a une similarité de nom, pour éviter les affichages redondants." -#: agenda_culturel/models.py:719 +#: agenda_culturel/models.py:764 msgid "Organisation" msgstr "Organisme" -#: agenda_culturel/models.py:720 +#: agenda_culturel/models.py:765 msgid "Organisations" msgstr "Organismes" -#: agenda_culturel/models.py:731 agenda_culturel/models.py:2688 +#: agenda_culturel/models.py:776 agenda_culturel/models.py:2841 msgid "Published" msgstr "Publié" -#: agenda_culturel/models.py:732 +#: agenda_culturel/models.py:777 msgid "Draft" msgstr "Brouillon" -#: agenda_culturel/models.py:733 +#: agenda_culturel/models.py:778 msgid "Trash" msgstr "Corbeille" -#: agenda_culturel/models.py:743 +#: agenda_culturel/models.py:788 msgid "Author currently editing/moderating the event" msgstr "" -#: agenda_culturel/models.py:753 +#: agenda_culturel/models.py:798 msgid "Author of the event creation" msgstr "Auteur de la création de l'événement" -#: agenda_culturel/models.py:762 +#: agenda_culturel/models.py:807 msgid "Author of the last importation" msgstr "Auteur de la dernière importation" -#: agenda_culturel/models.py:771 +#: agenda_culturel/models.py:816 msgid "Author of the last modification" msgstr "Auteur de la dernière modification" -#: agenda_culturel/models.py:780 +#: agenda_culturel/models.py:825 msgid "Author of the last moderation" msgstr "Auteur de la dernière modération" -#: agenda_culturel/models.py:791 +#: agenda_culturel/models.py:836 msgid "Title" msgstr "Titre" -#: agenda_culturel/models.py:808 +#: agenda_culturel/models.py:853 msgid "Start day" msgstr "Date de début" -#: agenda_culturel/models.py:810 +#: agenda_culturel/models.py:855 msgid "Start time" msgstr "Heure de début" -#: agenda_culturel/models.py:816 +#: agenda_culturel/models.py:861 msgid "End day" msgstr "Date de fin" -#: agenda_culturel/models.py:820 +#: agenda_culturel/models.py:865 msgid "End time" msgstr "Heure de fin" -#: agenda_culturel/models.py:823 +#: agenda_culturel/models.py:868 msgid "Recurrence" msgstr "Récurrence" -#: agenda_culturel/models.py:837 +#: agenda_culturel/models.py:882 msgid "Location (free form)" msgstr "Localisation (forme libre)" -#: agenda_culturel/models.py:839 +#: agenda_culturel/models.py:884 msgid "" "Address of the event in case its not available in the already known places " "(free form)" @@ -772,11 +805,11 @@ msgstr "" "Adresse d'un événement si elle n'est pas déjà présente dans la liste des " "lieux disponibles (forme libre)" -#: agenda_culturel/models.py:848 +#: agenda_culturel/models.py:893 msgid "Local event" msgstr "Événement de portée locale" -#: agenda_culturel/models.py:850 +#: agenda_culturel/models.py:895 msgid "" "If the event is a local event, it will not be proposed by default in daily, " "weekly or monthly views, unless the user has explicitly indicated that he " @@ -786,11 +819,11 @@ msgstr "" "les vues quotidiennes, hebdomadaires ou mensuelles, sauf si l'utilisateur a " "explicitement indiqué qu'il souhaite voir ces événements." -#: agenda_culturel/models.py:866 +#: agenda_culturel/models.py:911 msgid "Organisers" msgstr "Organisateurs" -#: agenda_culturel/models.py:868 +#: agenda_culturel/models.py:913 msgid "" "list of event organisers. Organizers will only be displayed if one of them " "does not normally use the venue." @@ -798,112 +831,112 @@ msgstr "" "Liste des organisateurs de l'événements. Les organisateurs seront affichés " "uniquement si au moins un d'entre eux n'utilise pas habituellement le lieu." -#: agenda_culturel/models.py:882 +#: agenda_culturel/models.py:927 msgid "Illustration (URL)" msgstr "Illustration (URL)" -#: agenda_culturel/models.py:883 +#: agenda_culturel/models.py:928 msgid "External URL of the illustration image" msgstr "URL externe de l'image illustrative" -#: agenda_culturel/models.py:889 +#: agenda_culturel/models.py:934 msgid "Illustration description" msgstr "Description de l'illustration" -#: agenda_culturel/models.py:890 +#: agenda_culturel/models.py:935 msgid "Alternative text used by screen readers for the image" msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" -#: agenda_culturel/models.py:898 +#: agenda_culturel/models.py:943 msgid "Importation source" msgstr "Source d'importation" -#: agenda_culturel/models.py:899 +#: agenda_culturel/models.py:944 msgid "Importation source used to detect removed entries." msgstr "Source d'importation utilisée pour détecter les éléments supprimés/" -#: agenda_culturel/models.py:905 +#: agenda_culturel/models.py:950 msgid "UUIDs" msgstr "UUIDs" -#: agenda_culturel/models.py:906 +#: agenda_culturel/models.py:951 msgid "UUIDs from import to detect duplicated entries." msgstr "UUIDs utilisés pendant l'import pour détecter les entrées dupliquées" -#: agenda_culturel/models.py:912 +#: agenda_culturel/models.py:957 msgid "Online sources or ticketing" msgstr "Sources en ligne ou billetterie" -#: agenda_culturel/models.py:926 +#: agenda_culturel/models.py:971 msgid "Other versions" msgstr "" -#: agenda_culturel/models.py:1049 +#: agenda_culturel/models.py:1095 msgid "Events" msgstr "Événements" -#: agenda_culturel/models.py:1105 +#: agenda_culturel/models.py:1256 msgid "recurrent import" msgstr "import récurrent" -#: agenda_culturel/models.py:1107 +#: agenda_culturel/models.py:1258 msgid "a non authenticated user" msgstr "un utilisateur non connecté" -#: agenda_culturel/models.py:1589 +#: agenda_culturel/models.py:1741 msgid "Your event has been published" msgstr "Ton événement a été publié" -#: agenda_culturel/models.py:1594 +#: agenda_culturel/models.py:1746 msgid "Your message has not been retained" msgstr "Ton événement n'a pas été retenu" -#: agenda_culturel/models.py:1682 agenda_culturel/models.py:2498 +#: agenda_culturel/models.py:1834 agenda_culturel/models.py:2650 msgid "Warning" msgstr "Warning" -#: agenda_culturel/models.py:1684 agenda_culturel/models.py:1790 +#: agenda_culturel/models.py:1836 agenda_culturel/models.py:1942 msgid "the date has not been imported correctly." msgstr "la date n'a pas été importée correctement." -#: agenda_culturel/models.py:1772 +#: agenda_culturel/models.py:1924 msgid "during import process" msgstr "pendant le processus d'import" -#: agenda_culturel/models.py:1788 agenda_culturel/models.py:1798 -#: agenda_culturel/models.py:1809 +#: agenda_culturel/models.py:1940 agenda_culturel/models.py:1950 +#: agenda_culturel/models.py:1961 msgid "warning" msgstr "attention" -#: agenda_culturel/models.py:1800 +#: agenda_culturel/models.py:1952 msgid "the title has not been imported correctly." msgstr "le titre n'a pas été importé correctement." -#: agenda_culturel/models.py:1812 +#: agenda_culturel/models.py:1964 msgid "The import was unable to find an event in the page." msgstr "L'import a été incapable de trouver un événement dans la page." -#: agenda_culturel/models.py:2160 +#: agenda_culturel/models.py:2312 msgid "Updated field(s): " msgstr "Champ(s) mis à jour: " -#: agenda_culturel/models.py:2164 +#: agenda_culturel/models.py:2316 msgid "Update" msgstr "Mise à jour" -#: agenda_culturel/models.py:2165 +#: agenda_culturel/models.py:2317 msgid "update process" msgstr "processus de mise à jour" -#: agenda_culturel/models.py:2234 +#: agenda_culturel/models.py:2386 msgid "Import" msgstr "Import" -#: agenda_culturel/models.py:2235 +#: agenda_culturel/models.py:2387 msgid "import process" msgstr "processus d'import" -#: agenda_culturel/models.py:2237 +#: agenda_culturel/models.py:2389 msgid "" "The duration of the event is a little too long for direct publication. " "Moderators can choose to publish it or not." @@ -911,187 +944,191 @@ msgstr "" "La durée de l'événement est un peu trop longue pour qu'il soit publié " "directement. Les modérateurs peuvent choisir de le publier ou non." -#: agenda_culturel/models.py:2489 +#: agenda_culturel/models.py:2641 msgid "From contributor" msgstr "D'un·e contributeurice" -#: agenda_culturel/models.py:2490 +#: agenda_culturel/models.py:2642 msgid "Import process" msgstr "Processus d'import" -#: agenda_culturel/models.py:2491 +#: agenda_culturel/models.py:2643 msgid "Update process" msgstr "Processus de mise à jour" -#: agenda_culturel/models.py:2492 +#: agenda_culturel/models.py:2644 msgid "Contact form" msgstr "Formulaire de contact" -#: agenda_culturel/models.py:2493 +#: agenda_culturel/models.py:2645 msgid "Event report" msgstr "Signalemet d'événement" -#: agenda_culturel/models.py:2496 +#: agenda_culturel/models.py:2648 msgid "From contributor (without message)" msgstr "D'un·e contributeurice (sans message)" -#: agenda_culturel/models.py:2502 +#: agenda_culturel/models.py:2654 msgid "Messages" msgstr "Messages" -#: agenda_culturel/models.py:2511 +#: agenda_culturel/models.py:2663 msgid "Subject" msgstr "Sujet" -#: agenda_culturel/models.py:2512 +#: agenda_culturel/models.py:2664 msgid "The subject of your message" msgstr "Sujet de votre message" -#: agenda_culturel/models.py:2518 +#: agenda_culturel/models.py:2670 msgid "Related event" msgstr "Événement associé" -#: agenda_culturel/models.py:2519 +#: agenda_culturel/models.py:2671 msgid "The message is associated with this event." msgstr "Le message est associé à cet événement." -#: agenda_culturel/models.py:2527 +#: agenda_culturel/models.py:2679 msgid "Author of the message" msgstr "Auteur du message" -#: agenda_culturel/models.py:2535 +#: agenda_culturel/models.py:2687 msgid "Your name" msgstr "Votre nom" -#: agenda_culturel/models.py:2541 +#: agenda_culturel/models.py:2693 msgid "Email address" msgstr "Adresse email" -#: agenda_culturel/models.py:2548 +#: agenda_culturel/models.py:2700 msgid "Your message" msgstr "Votre message" -#: agenda_culturel/models.py:2555 +#: agenda_culturel/models.py:2707 msgid "This message is a spam." msgstr "Ce message est un spam." -#: agenda_culturel/models.py:2562 +#: agenda_culturel/models.py:2714 msgid "this message has been processed and no longer needs to be handled" msgstr "Ce message a été traité et ne nécessite plus d'être pris en charge" -#: agenda_culturel/models.py:2568 +#: agenda_culturel/models.py:2720 msgid "Comments on the message from the moderation team" msgstr "Commentaires sur ce message par l'équipe de modération" -#: agenda_culturel/models.py:2601 agenda_culturel/models.py:2806 +#: agenda_culturel/models.py:2753 agenda_culturel/models.py:2929 msgid "Recurrent import" msgstr "Import récurrent" -#: agenda_culturel/models.py:2602 +#: agenda_culturel/models.py:2754 msgid "Recurrent imports" msgstr "Imports récurrents" -#: agenda_culturel/models.py:2606 +#: agenda_culturel/models.py:2758 msgid "ical" msgstr "ical" -#: agenda_culturel/models.py:2607 +#: agenda_culturel/models.py:2759 msgid "ical no busy" msgstr "ical sans busy" -#: agenda_culturel/models.py:2608 +#: agenda_culturel/models.py:2760 msgid "ical no VC" msgstr "ical sans VC" -#: agenda_culturel/models.py:2609 +#: agenda_culturel/models.py:2761 msgid "ical naive timezone" msgstr "ical timezone naïve" -#: agenda_culturel/models.py:2610 +#: agenda_culturel/models.py:2762 msgid "lacoope.org" msgstr "lacoope.org" -#: agenda_culturel/models.py:2611 +#: agenda_culturel/models.py:2763 msgid "la comédie" msgstr "la comédie" -#: agenda_culturel/models.py:2612 +#: agenda_culturel/models.py:2764 msgid "le fotomat" msgstr "le fotomat" -#: agenda_culturel/models.py:2613 +#: agenda_culturel/models.py:2765 msgid "la puce à l'oreille" msgstr "la puce à loreille" -#: agenda_culturel/models.py:2614 +#: agenda_culturel/models.py:2766 msgid "Plugin wordpress MEC" msgstr "Plugin wordpress MEC" -#: agenda_culturel/models.py:2615 +#: agenda_culturel/models.py:2767 msgid "Événements d'une page FB" msgstr "Événements d'une page FB" -#: agenda_culturel/models.py:2616 +#: agenda_culturel/models.py:2768 msgid "Billetterie Clermont-Ferrand" msgstr "" -#: agenda_culturel/models.py:2617 +#: agenda_culturel/models.py:2769 msgid "Arachnée concert" msgstr "Arachnée concert" -#: agenda_culturel/models.py:2618 +#: agenda_culturel/models.py:2770 msgid "Le Rio" msgstr "Le Rio" -#: agenda_culturel/models.py:2619 +#: agenda_culturel/models.py:2771 msgid "La Raymonde" msgstr "La Raymone" -#: agenda_culturel/models.py:2620 +#: agenda_culturel/models.py:2772 msgid "Agenda apidae tourisme" msgstr "Agenda apidae tourisme" -#: agenda_culturel/models.py:2621 +#: agenda_culturel/models.py:2773 msgid "Agenda iguana (médiathèques)" msgstr "Agenda iguana (médiathèques)" -#: agenda_culturel/models.py:2622 +#: agenda_culturel/models.py:2774 msgid "Mille formes" msgstr "Mille Formes" -#: agenda_culturel/models.py:2623 +#: agenda_culturel/models.py:2775 msgid "Les Amis du Temps des Cerises" msgstr "Les Amis du Temps des Cerises" -#: agenda_culturel/models.py:2624 +#: agenda_culturel/models.py:2776 msgid "Mobilizon" msgstr "Mobilizon" -#: agenda_culturel/models.py:2627 +#: agenda_culturel/models.py:2777 +msgid "Le caméléon" +msgstr "" + +#: agenda_culturel/models.py:2780 msgid "simple" msgstr "simple" -#: agenda_culturel/models.py:2628 +#: agenda_culturel/models.py:2781 msgid "Headless Chromium" msgstr "chromium sans interface" -#: agenda_culturel/models.py:2631 +#: agenda_culturel/models.py:2784 msgid "Headless Chromium (pause)" msgstr "chromium sans interface (pause)" -#: agenda_culturel/models.py:2637 +#: agenda_culturel/models.py:2790 msgid "daily" msgstr "chaque jour" -#: agenda_culturel/models.py:2639 +#: agenda_culturel/models.py:2792 msgid "weekly" msgstr "chaque semaine" -#: agenda_culturel/models.py:2640 +#: agenda_culturel/models.py:2793 msgid "never" msgstr "jamais" -#: agenda_culturel/models.py:2645 +#: agenda_culturel/models.py:2798 msgid "" "Recurrent import name. Be careful to choose a name that is easy to " "understand, as it will be public and displayed on the sites About page." @@ -1099,151 +1136,151 @@ msgstr "" "Nom de l'import récurrent. Attention à choisir un nom compréhensible, car il " "sera public, et affiché sur la page à propos du site." -#: agenda_culturel/models.py:2652 +#: agenda_culturel/models.py:2805 msgid "Processor" msgstr "Processeur" -#: agenda_culturel/models.py:2658 +#: agenda_culturel/models.py:2811 msgid "Downloader" msgstr "Téléchargeur" -#: agenda_culturel/models.py:2665 +#: agenda_culturel/models.py:2818 msgid "Import recurrence" msgstr "Récurrence d'import" -#: agenda_culturel/models.py:2672 +#: agenda_culturel/models.py:2825 msgid "Source" msgstr "Source" -#: agenda_culturel/models.py:2673 +#: agenda_culturel/models.py:2826 msgid "URL of the source document" msgstr "URL du document source" -#: agenda_culturel/models.py:2678 +#: agenda_culturel/models.py:2831 msgid "Browsable url" msgstr "URL navigable" -#: agenda_culturel/models.py:2680 +#: agenda_culturel/models.py:2833 msgid "URL of the corresponding document that will be shown to visitors." msgstr "URL correspondant au document et qui sera montrée aux visiteurs" -#: agenda_culturel/models.py:2689 +#: agenda_culturel/models.py:2842 msgid "Status of each imported event (published or draft)" msgstr "Status de chaque événement importé (publié ou brouillon)" -#: agenda_culturel/models.py:2694 +#: agenda_culturel/models.py:2847 msgid "Address for each imported event" msgstr "Adresse de chaque événement importé" -#: agenda_culturel/models.py:2701 +#: agenda_culturel/models.py:2854 msgid "Force location" msgstr "Focer la localisation" -#: agenda_culturel/models.py:2702 +#: agenda_culturel/models.py:2855 msgid "force location even if another is detected." msgstr "Forcer la localisation même si une autre a été détectée." -#: agenda_culturel/models.py:2708 +#: agenda_culturel/models.py:2861 msgid "Organiser" msgstr "Organisateur" -#: agenda_culturel/models.py:2709 +#: agenda_culturel/models.py:2862 msgid "Organiser of each imported event" msgstr "Organisateur de chaque événement importé" -#: agenda_culturel/models.py:2719 +#: agenda_culturel/models.py:2872 msgid "Category of each imported event" msgstr "Catégorie de chaque événement importé" -#: agenda_culturel/models.py:2727 +#: agenda_culturel/models.py:2880 msgid "Tags for each imported event" msgstr "Étiquettes de chaque événement importé" -#: agenda_culturel/models.py:2728 +#: agenda_culturel/models.py:2881 msgid "A list of tags that describe each imported event." msgstr "Une liste d'étiquettes décrivant chaque événement importé" -#: agenda_culturel/models.py:2787 +#: agenda_culturel/models.py:2910 msgid "Running" msgstr "En cours" -#: agenda_culturel/models.py:2788 +#: agenda_culturel/models.py:2911 msgid "Canceled" msgstr "Annulé" -#: agenda_culturel/models.py:2789 +#: agenda_culturel/models.py:2912 msgid "Success" msgstr "Succès" -#: agenda_culturel/models.py:2790 +#: agenda_culturel/models.py:2913 msgid "Failed" msgstr "Erreur" -#: agenda_culturel/models.py:2793 +#: agenda_culturel/models.py:2916 msgid "Batch importation" msgstr "Importation par lot" -#: agenda_culturel/models.py:2794 +#: agenda_culturel/models.py:2917 msgid "Batch importations" msgstr "Importations par lot" -#: agenda_culturel/models.py:2807 +#: agenda_culturel/models.py:2930 msgid "Reference to the recurrent import processing" msgstr "Référence du processus d'import récurrent" -#: agenda_culturel/models.py:2815 +#: agenda_culturel/models.py:2938 msgid "URL (if not recurrent import)" msgstr "URL (si pas d'import récurrent)" -#: agenda_culturel/models.py:2816 +#: agenda_culturel/models.py:2939 msgid "Source URL if no RecurrentImport is associated." msgstr "URL source si aucun import récurrent n'est associé" -#: agenda_culturel/models.py:2831 +#: agenda_culturel/models.py:2954 msgid "Error message" msgstr "Votre message" -#: agenda_culturel/models.py:2835 +#: agenda_culturel/models.py:2958 msgid "Number of collected events" msgstr "Nombre d'événements collectés" -#: agenda_culturel/models.py:2838 +#: agenda_culturel/models.py:2961 msgid "Number of imported events" msgstr "Nombre d'événements importés" -#: agenda_culturel/models.py:2841 +#: agenda_culturel/models.py:2964 msgid "Number of updated events" msgstr "Nombre d'événements mis à jour" -#: agenda_culturel/models.py:2844 +#: agenda_culturel/models.py:2967 msgid "Number of removed events" msgstr "Nombre d'événements supprimés" -#: agenda_culturel/models.py:2852 +#: agenda_culturel/models.py:2975 msgid "Weight" msgstr "Poids" -#: agenda_culturel/models.py:2853 +#: agenda_culturel/models.py:2976 msgid "The lower is the weight, the earlier the filter is applied" msgstr "Plus le poids est léger, plus le filtre sera appliqué tôt" -#: agenda_culturel/models.py:2860 +#: agenda_culturel/models.py:2983 msgid "Category applied to the event" msgstr "Catégorie appliquée à l'événement" -#: agenda_culturel/models.py:2865 +#: agenda_culturel/models.py:2988 msgid "Contained in the title" msgstr "Contenu dans le titre" -#: agenda_culturel/models.py:2866 +#: agenda_culturel/models.py:2989 msgid "Text contained in the event title" msgstr "Texte contenu dans le titre de l'événement" -#: agenda_culturel/models.py:2872 +#: agenda_culturel/models.py:2995 msgid "Exact title extract" msgstr "Extrait exact du titre" -#: agenda_culturel/models.py:2874 +#: agenda_culturel/models.py:2997 msgid "" "If checked, the extract will be searched for in the title using the exact " "form (capitals, accents)." @@ -1251,19 +1288,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans le titre en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:2880 +#: agenda_culturel/models.py:3003 msgid "Contained in the description" msgstr "Contenu dans la description" -#: agenda_culturel/models.py:2881 +#: agenda_culturel/models.py:3004 msgid "Text contained in the description" msgstr "Texte contenu dans la description" -#: agenda_culturel/models.py:2887 +#: agenda_culturel/models.py:3010 msgid "Exact description extract" msgstr "Extrait exact de description" -#: agenda_culturel/models.py:2889 +#: agenda_culturel/models.py:3012 msgid "" "If checked, the extract will be searched for in the description using the " "exact form (capitals, accents)." @@ -1271,19 +1308,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans la description en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:2895 +#: agenda_culturel/models.py:3018 msgid "Contained in the location" msgstr "Contenu dans la localisation" -#: agenda_culturel/models.py:2896 +#: agenda_culturel/models.py:3019 msgid "Text contained in the event location" msgstr "Texte contenu dans la localisation de l'événement" -#: agenda_culturel/models.py:2902 +#: agenda_culturel/models.py:3025 msgid "Exact location extract" msgstr "Extrait exact de localisation" -#: agenda_culturel/models.py:2904 +#: agenda_culturel/models.py:3027 msgid "" "If checked, the extract will be searched for in the location using the exact " "form (capitals, accents)." @@ -1291,59 +1328,59 @@ msgstr "" "Si coché, l'extrait sera recherché dans la localisation en utilisant la " "forme exacte (majuscules, accents)" -#: agenda_culturel/models.py:2912 +#: agenda_culturel/models.py:3035 msgid "Location from place" msgstr "Localisation depuis le lieu" -#: agenda_culturel/models.py:2921 +#: agenda_culturel/models.py:3044 msgid "Categorisation rule" msgstr "Règle de catégorisation" -#: agenda_culturel/models.py:2922 +#: agenda_culturel/models.py:3045 msgid "Categorisation rules" msgstr "Règles de catégorisation" -#: agenda_culturel/settings/base.py:180 +#: agenda_culturel/settings/base.py:183 msgid "French" msgstr "français" -#: agenda_culturel/views.py:158 +#: agenda_culturel/views.py:170 msgid "Recurrent import name" msgstr "Nome de l'import récurrent" -#: agenda_culturel/views.py:159 +#: agenda_culturel/views.py:171 msgid "Add another" msgstr "Ajouter un autre" -#: agenda_culturel/views.py:160 +#: agenda_culturel/views.py:172 msgid "Browse..." msgstr "Naviguer..." -#: agenda_culturel/views.py:161 +#: agenda_culturel/views.py:173 msgid "No file selected." msgstr "Pas de fichier sélectionné." -#: agenda_culturel/views.py:179 +#: agenda_culturel/views.py:191 msgid ": error 500" msgstr ": erreur 500" -#: agenda_culturel/views.py:180 +#: agenda_culturel/views.py:192 msgid "An internal error has occurred on site {} at address {}." msgstr "Une erreur interne s'est produite sur le site {} à l'adresse {}." -#: agenda_culturel/views.py:219 +#: agenda_culturel/views.py:231 msgid "Moderation rules" msgstr "Règles de modération" -#: agenda_culturel/views.py:228 +#: agenda_culturel/views.py:240 msgid "Import requirements" msgstr "Besoins pour l'import" -#: agenda_culturel/views.py:434 +#: agenda_culturel/views.py:446 msgid "The static content has been successfully updated." msgstr "Le contenu statique a été modifié avec succès." -#: agenda_culturel/views.py:445 +#: agenda_culturel/views.py:457 msgid "" "The event cannot be updated because the import process is not available for " "the referenced sources." @@ -1351,21 +1388,21 @@ msgstr "" "La mise à jour de l'événement n'est pas possible car le processus d'import " "n'est pas disponible pour les sources référencées." -#: agenda_culturel/views.py:458 +#: agenda_culturel/views.py:470 msgid "The event update has been queued and will be completed shortly." msgstr "" "La mise à jour de l'événement a été mise en attente et sera effectuée sous " "peu." -#: agenda_culturel/views.py:487 agenda_culturel/views.py:571 +#: agenda_culturel/views.py:499 agenda_culturel/views.py:583 msgid " A message has been sent to the person who proposed the event." msgstr " Un message a été envoyé à la personne qui a proposé l'événement." -#: agenda_culturel/views.py:491 +#: agenda_culturel/views.py:503 msgid "The event has been successfully modified." msgstr "L'événement a été modifié avec succès." -#: agenda_culturel/views.py:515 +#: agenda_culturel/views.py:527 msgid "" "Changes will be visible on a local copy of the event. The version identical " "to the imported source will be hidden." @@ -1373,19 +1410,19 @@ msgstr "" "Les modifications seront visibles sur une copie locale de l'événement. La " "version fidèle à la source importée sera masquée." -#: agenda_culturel/views.py:576 +#: agenda_culturel/views.py:588 msgid "The event {} has been moderated with success." msgstr "L'événement {} a été modéré avec succès." -#: agenda_culturel/views.py:725 +#: agenda_culturel/views.py:737 msgid "The event has been successfully deleted." msgstr "L'événement a été supprimé avec succès." -#: agenda_culturel/views.py:775 +#: agenda_culturel/views.py:817 msgid "Comment" msgstr "Commentaire" -#: agenda_culturel/views.py:801 +#: agenda_culturel/views.py:841 msgid "" "The status has been successfully modified and a message has been sent to the " "person who proposed the event." @@ -1393,15 +1430,15 @@ msgstr "" "Le status a été modifié avec succès et un message a été envoyé à la personne " "qui a proposé l'événement." -#: agenda_culturel/views.py:805 +#: agenda_culturel/views.py:845 msgid "The status has been successfully modified." msgstr "Le status a été modifié avec succès." -#: agenda_culturel/views.py:845 +#: agenda_culturel/views.py:885 msgid "The event was created: {}." msgstr "L'événement a été créé: {}." -#: agenda_culturel/views.py:851 +#: agenda_culturel/views.py:891 msgid "" "The event has been submitted and will be published as soon as it has been " "validated by the moderation team." @@ -1409,99 +1446,99 @@ msgstr "" "L'événement a été soumis et sera publié dès qu'il aura été validé par " "l'équipe de modération." -#: agenda_culturel/views.py:865 +#: agenda_culturel/views.py:905 msgid "during the creation process" msgstr "pendant le processus d'import" -#: agenda_culturel/views.py:888 +#: agenda_culturel/views.py:928 msgid "A message has been sent to the person who proposed the initial event." msgstr "" "Un message a été envoyé à la personne qui a proposé l'événement initial." -#: agenda_culturel/views.py:981 agenda_culturel/views.py:1059 +#: agenda_culturel/views.py:1021 agenda_culturel/views.py:1099 msgid "{} has not been submitted since its already known: {}." msgstr "{} n'a pas été soumis car il est déjà connu: {}." -#: agenda_culturel/views.py:990 agenda_culturel/views.py:1068 +#: agenda_culturel/views.py:1030 agenda_culturel/views.py:1108 msgid "" "{} has not been submitted since its already known and currently into " "moderation process." msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération" -#: agenda_culturel/views.py:1002 +#: agenda_culturel/views.py:1042 msgid "Integrating {} url(s) into our import process." msgstr "Intégration de {} url(s) dans notre processus d'import." -#: agenda_culturel/views.py:1077 +#: agenda_culturel/views.py:1117 msgid "Integrating {} into our import process." msgstr "Intégration de {} dans notre processus d'import." -#: agenda_culturel/views.py:1193 +#: agenda_culturel/views.py:1233 msgid "Your message has been sent successfully." msgstr "Votre message a été envoyé avec succès." -#: agenda_culturel/views.py:1226 +#: agenda_culturel/views.py:1266 msgid "Reporting the event {} on {}" msgstr "Signaler l'événement {} du {}" -#: agenda_culturel/views.py:1236 +#: agenda_culturel/views.py:1276 msgid "The contact message has been successfully deleted." msgstr "Le message de contact a été supprimé avec succès." -#: agenda_culturel/views.py:1252 +#: agenda_culturel/views.py:1292 msgid "The contact message properties has been successfully modified." msgstr "Les propriétés du message de contact ont été modifié avec succès." -#: agenda_culturel/views.py:1430 +#: agenda_culturel/views.py:1470 msgid "Spam has been successfully deleted." msgstr "Le spam a été supprimé avec succès" -#: agenda_culturel/views.py:1607 +#: agenda_culturel/views.py:1647 msgid "The import has been run successfully." msgstr "L'import a été lancé avec succès" -#: agenda_culturel/views.py:1629 +#: agenda_culturel/views.py:1669 msgid "The import has been canceled." msgstr "L'import a été annulé" -#: agenda_culturel/views.py:1652 +#: agenda_culturel/views.py:1692 msgid "The orphan event update has been launched." msgstr "La mise à jour de l'événement orphelin a été lancée." -#: agenda_culturel/views.py:1748 +#: agenda_culturel/views.py:1788 msgid "The recurrent import has been successfully modified." msgstr "L'import récurrent a été modifié avec succès." -#: agenda_culturel/views.py:1760 +#: agenda_culturel/views.py:1800 msgid "The recurrent import has been successfully deleted." msgstr "L'import récurrent a été supprimé avec succès" -#: agenda_culturel/views.py:1806 +#: agenda_culturel/views.py:1846 msgid "The import has been launched." msgstr "L'import a été lancé" -#: agenda_culturel/views.py:1833 +#: agenda_culturel/views.py:1873 msgid "Imports has been launched." msgstr "Les imports ont été lancés" -#: agenda_culturel/views.py:1855 +#: agenda_culturel/views.py:1895 msgid "Facebook imports has been launched." msgstr "Les imports Facebook ont été lancés" -#: agenda_culturel/views.py:1918 +#: agenda_culturel/views.py:1958 msgid "Update successfully completed." msgstr "Mise à jour réalisée avec succès." -#: agenda_culturel/views.py:1986 +#: agenda_culturel/views.py:2026 msgid "Creation of a merged event has been successfully completed." msgstr "Création d'un événement fusionné réalisée avec succès." -#: agenda_culturel/views.py:2023 +#: agenda_culturel/views.py:2063 msgid "Events have been marked as unduplicated." msgstr "Les événements ont été marqués comme non dupliqués." -#: agenda_culturel/views.py:2040 agenda_culturel/views.py:2057 -#: agenda_culturel/views.py:2085 +#: agenda_culturel/views.py:2080 agenda_culturel/views.py:2097 +#: agenda_culturel/views.py:2126 msgid "" "The selected item is no longer included in the list of duplicates. Someone " "else has probably modified the list in the meantime." @@ -1509,23 +1546,23 @@ msgstr "" "L'élément sélectionné ne fait plus partie de la liste des dupliqués. Une " "autre personne a probablement modifié la liste entre temps." -#: agenda_culturel/views.py:2047 +#: agenda_culturel/views.py:2087 msgid "The selected event has been set as representative" msgstr "L'événement sélectionné a été défini comme representatif." -#: agenda_culturel/views.py:2071 +#: agenda_culturel/views.py:2112 msgid "The event has been withdrawn from the group and made independent." msgstr "L'événement a été retiré du groupe et rendu indépendant." -#: agenda_culturel/views.py:2121 +#: agenda_culturel/views.py:2162 msgid "Cleaning up duplicates: {} item(s) fixed." msgstr "Nettoyage des dupliqués: {} élément(s) corrigé(s)." -#: agenda_culturel/views.py:2170 +#: agenda_culturel/views.py:2211 msgid "The event was successfully duplicated." msgstr "L'événement a été marqué dupliqué avec succès." -#: agenda_culturel/views.py:2178 +#: agenda_culturel/views.py:2219 msgid "" "The event has been successfully flagged as a duplicate. The moderation team " "will deal with your suggestion shortly." @@ -1533,32 +1570,32 @@ msgstr "" "L'événement a été signalé comme dupliqué avec succès. Votre suggestion sera " "prochainement prise en charge par l'équipe de modération." -#: agenda_culturel/views.py:2240 +#: agenda_culturel/views.py:2281 msgid "The categorisation rule has been successfully modified." msgstr "La règle de catégorisation a été modifiée avec succès." -#: agenda_culturel/views.py:2252 +#: agenda_culturel/views.py:2293 msgid "The categorisation rule has been successfully deleted." msgstr "La règle de catégorisation a été supprimée avec succès" -#: agenda_culturel/views.py:2274 +#: agenda_culturel/views.py:2315 msgid "The rules were successfully applied and 1 event was categorised." msgstr "" "Les règles ont été appliquées avec succès et 1 événement a été catégorisé" -#: agenda_culturel/views.py:2281 +#: agenda_culturel/views.py:2322 msgid "The rules were successfully applied and {} events were categorised." msgstr "" "Les règles ont été appliquées avec succès et {} événements ont été " "catégorisés" -#: agenda_culturel/views.py:2288 agenda_culturel/views.py:2352 +#: agenda_culturel/views.py:2329 agenda_culturel/views.py:2393 msgid "The rules were successfully applied and no events were categorised." msgstr "" "Les règles ont été appliquées avec succès et aucun événement n'a été " "catégorisé" -#: agenda_culturel/views.py:2338 +#: agenda_culturel/views.py:2379 msgid "" "The rules were successfully applied and 1 event with default category was " "categorised." @@ -1566,7 +1603,7 @@ msgstr "" "Les règles ont été appliquées avec succès et 1 événement avec catégorie par " "défaut a été catégorisé" -#: agenda_culturel/views.py:2345 +#: agenda_culturel/views.py:2386 msgid "" "The rules were successfully applied and {} events with default category were " "categorised." @@ -1574,58 +1611,58 @@ msgstr "" "Les règles ont été appliquées avec succès et {} événements avec catégorie " "par défaut ont été catégorisés" -#: agenda_culturel/views.py:2451 agenda_culturel/views.py:2513 -#: agenda_culturel/views.py:2553 +#: agenda_culturel/views.py:2492 agenda_culturel/views.py:2554 +#: agenda_culturel/views.py:2594 msgid "{} events have been updated." msgstr "{} événements ont été mis à jour." -#: agenda_culturel/views.py:2454 agenda_culturel/views.py:2515 -#: agenda_culturel/views.py:2556 +#: agenda_culturel/views.py:2495 agenda_culturel/views.py:2556 +#: agenda_culturel/views.py:2597 msgid "1 event has been updated." msgstr "1 événement a été mis à jour" -#: agenda_culturel/views.py:2456 agenda_culturel/views.py:2517 -#: agenda_culturel/views.py:2558 +#: agenda_culturel/views.py:2497 agenda_culturel/views.py:2558 +#: agenda_culturel/views.py:2599 msgid "No events have been modified." msgstr "Aucun événement n'a été modifié." -#: agenda_culturel/views.py:2465 +#: agenda_culturel/views.py:2506 msgid "The place has been successfully updated." msgstr "Le lieu a été modifié avec succès." -#: agenda_culturel/views.py:2474 +#: agenda_culturel/views.py:2515 msgid "The place has been successfully created." msgstr "Le lieu a été créé avec succès." -#: agenda_culturel/views.py:2540 +#: agenda_culturel/views.py:2581 msgid "The selected place has been assigned to the event." msgstr "Le lieu sélectionné a été assigné à l'événement." -#: agenda_culturel/views.py:2545 +#: agenda_culturel/views.py:2586 msgid "A new alias has been added to the selected place." msgstr "Un nouvel alias a été créé pour le lieu sélectionné." -#: agenda_culturel/views.py:2672 +#: agenda_culturel/views.py:2713 msgid "The organisation has been successfully updated." msgstr "L'organisme a été modifié avec succès." -#: agenda_culturel/views.py:2679 +#: agenda_culturel/views.py:2720 msgid "The organisation has been successfully created." msgstr "L'organisme a été créé avec succès." -#: agenda_culturel/views.py:2698 +#: agenda_culturel/views.py:2739 msgid "The tag has been successfully updated." msgstr "L'étiquette a été modifiée avec succès." -#: agenda_culturel/views.py:2705 +#: agenda_culturel/views.py:2746 msgid "The tag has been successfully created." msgstr "L'étiquette a été créée avec succès." -#: agenda_culturel/views.py:2874 +#: agenda_culturel/views.py:2957 msgid "You have not modified the tag name." msgstr "Vous n'avez pas modifié le nom de l'étiquette." -#: agenda_culturel/views.py:2889 +#: agenda_culturel/views.py:2972 msgid "" "This tag {} is already in use, and is described by different information " "from the current tag. You can force renaming by checking the corresponding " @@ -1638,7 +1675,7 @@ msgstr "" "sera supprimée, et tous les événements associés à l'étiquette {} seront " "associés à l'étiquette {}." -#: agenda_culturel/views.py:2903 +#: agenda_culturel/views.py:2986 msgid "" "This tag {} is already in use. You can force renaming by checking the " "corresponding option." @@ -1646,24 +1683,18 @@ msgstr "" "Cette étiquette {} est déjà utilisée. Vous pouvez forcer le renommage en " "cochant l'option correspondante." -#: agenda_culturel/views.py:2936 +#: agenda_culturel/views.py:3019 msgid "The tag {} has been successfully renamed to {}." msgstr "L'étiquette {} a été renommée avec succès en {}." -#: agenda_culturel/views.py:2978 +#: agenda_culturel/views.py:3061 msgid "The tag {} has been successfully deleted." msgstr "L'événement {} a été supprimé avec succès." -#: agenda_culturel/views.py:3004 +#: agenda_culturel/views.py:3087 msgid "Cache successfully cleared." msgstr "Le cache a été vidé avec succès." -#: agenda_culturel/views.py:3019 +#: agenda_culturel/views.py:3102 msgid "Your user profile has been successfully modified." msgstr "Votre profil utilisateur a été modifié avec succès." - -#~ msgid "standard deviation" -#~ msgstr "écart-type" - -#~ msgid "la cour des 3 coquins" -#~ msgstr "la cour des 3 coquins" diff --git a/src/agenda_culturel/migrations/0161_siteconfiguration.py b/src/agenda_culturel/migrations/0161_siteconfiguration.py new file mode 100644 index 0000000..cd10afc --- /dev/null +++ b/src/agenda_culturel/migrations/0161_siteconfiguration.py @@ -0,0 +1,102 @@ +# Generated by Django 4.2.19 on 2025-04-02 19:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("agenda_culturel", "0160_alter_recurrentimport_processor"), + ] + + operations = [ + migrations.CreateModel( + name="SiteConfiguration", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "site_name", + models.CharField( + default="Pommes de lune", + max_length=255, + verbose_name="Site name", + ), + ), + ( + "site_description", + models.CharField( + default="Agenda participatif des sorties culturelles à Clermont-Ferrand et aux environs", + max_length=255, + verbose_name="Site description", + ), + ), + ( + "html_keywords", + models.CharField( + default="Clermont-Ferrand, Puy-de-Dôme, agenda culturel, agenda participatif, sortir à clermont, sorties, concerts, théâtre, danse, animations, ateliers, lectures", + max_length=1024, + verbose_name="Keywords in html header", + ), + ), + ( + "html_description", + models.CharField( + default="Où sortir à Clermont-Ferrand? Retrouve tous les bons plans sur l'agenda participatif des événements culturels à Clermont-Ferrand et dans le Puy-de-Dôme", + max_length=1024, + verbose_name="Description in html header", + ), + ), + ( + "google_site_verification", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Google site verification value", + ), + ), + ( + "ms_site_verification", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Microsoft (bing) site verification value", + ), + ), + ( + "favicon", + models.ImageField( + blank=True, + max_length=1024, + null=True, + upload_to="", + verbose_name="Illustration", + ), + ), + ( + "favicon_dev", + models.ImageField( + blank=True, + max_length=1024, + null=True, + upload_to="", + verbose_name="Illustration (development version)", + ), + ), + ], + options={ + "verbose_name": "Site Configuration", + }, + ), + ] diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 854e7ed..7d5c4c6 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -46,7 +46,9 @@ from django.db.models.signals import post_save from django.db.models.functions import Now from django.db.models.functions import ExtractDay from django.db.models.expressions import RawSQL - +from django.templatetags.static import static +from django.conf import settings +from solo.models import SingletonModel from .calendar import CalendarDay from .import_tasks.extractor import Extractor @@ -62,6 +64,87 @@ logger = logging.getLogger(__name__) to_be_translated = [_("mean"), _("median"), _("maximum"), _("minimum"), _("stdev")] +class SiteConfiguration(SingletonModel): + site_name = models.CharField( + verbose_name=_("Site name"), max_length=255, default="Pommes de lune" + ) + site_description = models.CharField( + verbose_name=_("Site description"), + max_length=255, + default="Agenda participatif des sorties culturelles à Clermont-Ferrand et aux environs", + ) + + html_keywords = models.CharField( + verbose_name=_("Keywords in html header"), + max_length=1024, + default="Clermont-Ferrand, Puy-de-Dôme, agenda culturel, agenda participatif, sortir à clermont, sorties, concerts, théâtre, danse, animations, ateliers, lectures", + ) + html_description = models.CharField( + verbose_name=_("Description in html header"), + max_length=1024, + default="Où sortir à Clermont-Ferrand? Retrouve tous les bons plans sur l'agenda participatif des événements culturels à Clermont-Ferrand et dans le Puy-de-Dôme", + ) + google_site_verification = models.CharField( + verbose_name=_("Google site verification value"), + max_length=255, + default=None, + blank=True, + null=True, + ) + ms_site_verification = models.CharField( + verbose_name=_("Microsoft (bing) site verification value"), + max_length=255, + default=None, + blank=True, + null=True, + ) + + favicon = models.ImageField( + verbose_name=_("Illustration"), + max_length=1024, + blank=True, + null=True, + ) + favicon_dev = models.ImageField( + verbose_name=_("Illustration (development version)"), + max_length=1024, + blank=True, + null=True, + ) + + def guess_mimetype(url): + if url.endswith("png"): + return "image/png" + if url.endswith("jpg"): + return "image/jpg" + if url.endswith("svg"): + return "image/svg+xml" + if url.endswith("ico"): + return "image/x-icon" + return "image/jpg" + + def get_favicon_url(self): + if settings.DEBUG: + if self.favicon_dev: + return self.favicon_dev.url + else: + return static("images/pdl-64-dev.png") + else: + if self.favicon: + return self.favicon.url + else: + return static("images/pdl-64.png") + + def get_favicon_mimetype(self): + return SiteConfiguration.guess_mimetype(self.get_favicon_url()) + + def __str__(self): + return str(_("Site Configuration")) + + class Meta: + verbose_name = _("Site Configuration") + + class UserProfile(models.Model): user = models.OneToOneField( User, @@ -2453,7 +2536,10 @@ class Event(models.Model): def export_to_ics(events, request): cal = icalCal() # Some properties are required to be compliant - cal.add("prodid", "-//Pommes de lune//pommesdelune.fr//") + cal.add( + "prodid", + "-//" + SiteConfiguration.get_solo().site_name + "//pommesdelune.fr//", + ) cal.add("version", "2.0") for event in events: diff --git a/src/agenda_culturel/settings/base.py b/src/agenda_culturel/settings/base.py index da2b4f9..fb61dd2 100644 --- a/src/agenda_culturel/settings/base.py +++ b/src/agenda_culturel/settings/base.py @@ -66,8 +66,11 @@ INSTALLED_APPS = [ "template_profiler_panel", "django_cleanup.apps.CleanupConfig", "django_unused_media", + "solo.apps.SoloAppConfig", ] +SOLO_CACHE_TIMEOUT = 60 * 15 # 15 minutes + HONEYPOT_FIELD_NAME = "alias_name" MIDDLEWARE = [ diff --git a/src/agenda_culturel/templates/agenda_culturel/page.html b/src/agenda_culturel/templates/agenda_culturel/page.html index 48c165c..7aadc67 100644 --- a/src/agenda_culturel/templates/agenda_culturel/page.html +++ b/src/agenda_culturel/templates/agenda_culturel/page.html @@ -7,40 +7,39 @@ {% load duplicated_extra %} {% load rimports_extra %} {% load static %} + {% load solo_tags %} + {% get_solo 'agenda_culturel.SiteConfiguration' as site_config %} - Pommes de lune — + <title>{{ site_config.site_name }} — {% block title %}{% endblock %} - - - + {% if site_config.google_site_verification %} + + {% endif %} + {% if site_config.ms_site_verification %} + + {% endif %} + + content="{% block description %}{{ site_config.description }}{% endblock %}" /> {% load static %} + content="{{ site_config.site_name }} — {% block og_title %}{% endblock %}" /> + content="{% block og_description %}{{ site_config.description }}{% endblock %}" /> - {% if debug %} - - {% else %} - - {% endif %} + {% load compress %} {% compress css %}
  • - logo pommes de lune + logo {{ site_config.site_name }}
  • {% if user.is_authenticated %}{{ user.username }} @{% endif %} - Pommes de lune + {{ site_config.site_name }}
    -
    Agenda participatif des sorties culturelles à Clermont-Ferrand et aux environs
    +
    {{ site_config.site_description }}
  • diff --git a/src/agenda_culturel/templates/agenda_culturel/statistics.html b/src/agenda_culturel/templates/agenda_culturel/statistics.html index c7902ce..d8d9f01 100644 --- a/src/agenda_culturel/templates/agenda_culturel/statistics.html +++ b/src/agenda_culturel/templates/agenda_culturel/statistics.html @@ -4,6 +4,7 @@ {% block title %} {% block og_title %}Statistiques{% endblock %} {% endblock %} +{% load solo_tags %} {% load cat_extra %} {% block entete_header %} {% css_categories %} @@ -15,11 +16,14 @@ {% endblock %} {% block content %} + {% get_solo 'agenda_culturel.SiteConfiguration' as site_config %}

    Statistiques

    -

    On retrouve sur cette page une synthèse des événements publiés sur l'agenda culturel pommes de lune.

    +

    + On retrouve sur cette page une synthèse des événements publiés sur l'agenda culturel {{ site_config.site_name }}. +

    Par date de l'événement

    Pour chaque date, on retrouve le nombre d'événements qui débutent à cette date (sauf événements récurrents).

    diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index 827fedf..d91c73e 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -101,6 +101,7 @@ from .models import ( Tag, remove_accents, UserProfile, + SiteConfiguration, ) from .utils import PlaceGuesser @@ -1216,7 +1217,7 @@ def export_ical(request, cat=None, tag=None, organisation_pk=None, place_pk=None extra += " - " + emoji.replace_emoji(tag, replace="") response["Content-Disposition"] = "attachment; filename={0}{1}{2}".format( - "Pommes de lune", extra, ".ics" + SiteConfiguration.get_solo().site_name, extra, ".ics" ) return response diff --git a/src/requirements.txt b/src/requirements.txt index a3fbcd6..678cbac 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -50,3 +50,4 @@ requests==2.32.3 django-cleanup==9.0.0 django-unused-media==0.2.2 django-resized==1.0.3 +django-solo==2.4.0