Amélioration de la généricité
On créé une classe singleton pour les variables de configuration See #328
This commit is contained in:
parent
d2966348fd
commit
15cb6d815a
@ -28,6 +28,8 @@ On peut aussi peupler les positions de référence qui serviront aux recherches
|
|||||||
|
|
||||||
* ```make create-reference-locations```
|
* ```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
|
## Utilisation d'un proxy socket
|
||||||
|
|
||||||
On peut activer à la main (pour l'instant) un proxy type socket pour l'import d'événements.
|
On peut activer à la main (pour l'instant) un proxy type socket pour l'import d'événements.
|
||||||
|
@ -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.forms.widgets import DynamicArrayWidget
|
||||||
from django_better_admin_arrayfield.models.fields import DynamicArrayField
|
from django_better_admin_arrayfield.models.fields import DynamicArrayField
|
||||||
|
|
||||||
|
from solo.admin import SingletonModelAdmin
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
BatchImportation,
|
BatchImportation,
|
||||||
Category,
|
Category,
|
||||||
@ -17,8 +19,11 @@ from .models import (
|
|||||||
StaticContent,
|
StaticContent,
|
||||||
Tag,
|
Tag,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
|
SiteConfiguration,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
admin.site.register(SiteConfiguration, SingletonModelAdmin)
|
||||||
|
|
||||||
admin.site.register(Category)
|
admin.site.register(Category)
|
||||||
admin.site.register(Tag)
|
admin.site.register(Tag)
|
||||||
admin.site.register(StaticContent)
|
admin.site.register(StaticContent)
|
||||||
|
File diff suppressed because it is too large
Load Diff
102
src/agenda_culturel/migrations/0161_siteconfiguration.py
Normal file
102
src/agenda_culturel/migrations/0161_siteconfiguration.py
Normal file
@ -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",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -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 Now
|
||||||
from django.db.models.functions import ExtractDay
|
from django.db.models.functions import ExtractDay
|
||||||
from django.db.models.expressions import RawSQL
|
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 .calendar import CalendarDay
|
||||||
from .import_tasks.extractor import Extractor
|
from .import_tasks.extractor import Extractor
|
||||||
@ -62,6 +64,87 @@ logger = logging.getLogger(__name__)
|
|||||||
to_be_translated = [_("mean"), _("median"), _("maximum"), _("minimum"), _("stdev")]
|
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):
|
class UserProfile(models.Model):
|
||||||
user = models.OneToOneField(
|
user = models.OneToOneField(
|
||||||
User,
|
User,
|
||||||
@ -2453,7 +2536,10 @@ class Event(models.Model):
|
|||||||
def export_to_ics(events, request):
|
def export_to_ics(events, request):
|
||||||
cal = icalCal()
|
cal = icalCal()
|
||||||
# Some properties are required to be compliant
|
# 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")
|
cal.add("version", "2.0")
|
||||||
|
|
||||||
for event in events:
|
for event in events:
|
||||||
|
@ -66,8 +66,11 @@ INSTALLED_APPS = [
|
|||||||
"template_profiler_panel",
|
"template_profiler_panel",
|
||||||
"django_cleanup.apps.CleanupConfig",
|
"django_cleanup.apps.CleanupConfig",
|
||||||
"django_unused_media",
|
"django_unused_media",
|
||||||
|
"solo.apps.SoloAppConfig",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SOLO_CACHE_TIMEOUT = 60 * 15 # 15 minutes
|
||||||
|
|
||||||
HONEYPOT_FIELD_NAME = "alias_name"
|
HONEYPOT_FIELD_NAME = "alias_name"
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -7,40 +7,39 @@
|
|||||||
{% load duplicated_extra %}
|
{% load duplicated_extra %}
|
||||||
{% load rimports_extra %}
|
{% load rimports_extra %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load solo_tags %}
|
||||||
|
{% get_solo 'agenda_culturel.SiteConfiguration' as site_config %}
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Pommes de lune —
|
<title>{{ site_config.site_name }} —
|
||||||
{% block title %}{% endblock %}
|
{% block title %}{% endblock %}
|
||||||
</title>
|
</title>
|
||||||
|
{% if site_config.google_site_verification %}
|
||||||
<meta name="google-site-verification"
|
<meta name="google-site-verification"
|
||||||
content="pvRD0rc_xIE-1IYmbao0kj5ngGo1IWxJqKwoxrQwxuA" />
|
content="{{ site_config.google_site_verification }}" />
|
||||||
<meta name="msvalidate.01" content="60E9E7DB667A3C4D6697261420DF3D1B" />
|
{% endif %}
|
||||||
<meta name="keywords"
|
{% if site_config.ms_site_verification %}
|
||||||
content="Clermont-Ferrand, Puy-de-Dôme, agenda culturel, agenda participatif, sortir à clermont, sorties, concerts, théâtre, danse, animations, ateliers, lectures">
|
<meta name="msvalidate.01" content="{{ site_config.ms_site_verification }}" />
|
||||||
|
{% endif %}
|
||||||
|
<meta name="keywords" content="{{ site_config.keywords }}">
|
||||||
<meta name="description"
|
<meta name="description"
|
||||||
content="{% block description %}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{% endblock %}" />
|
content="{% block description %}{{ site_config.description }}{% endblock %}" />
|
||||||
<script src="{% static 'js/modal.js' %}"></script>
|
<script src="{% static 'js/modal.js' %}"></script>
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<meta property="og:title"
|
<meta property="og:title"
|
||||||
content="Pommes de lune — {% block og_title %}{% endblock %}" />
|
content="{{ site_config.site_name }} — {% block og_title %}{% endblock %}" />
|
||||||
<meta property="og:description"
|
<meta property="og:description"
|
||||||
content="{% block og_description %}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{% endblock %}" />
|
content="{% block og_description %}{{ site_config.description }}{% endblock %}" />
|
||||||
<meta property="og:image"
|
<meta property="og:image"
|
||||||
content="{% block og_image %}https://{{ request.get_host }}{% get_media_prefix %}screenshot.png{% endblock %}" />
|
content="{% block og_image %}https://{{ request.get_host }}{% get_media_prefix %}screenshot.png{% endblock %}" />
|
||||||
<meta property="og:locale" content="fr_FR" />
|
<meta property="og:locale" content="fr_FR" />
|
||||||
<meta property="og:url" content="{{ request.build_absolute_uri }}" />
|
<meta property="og:url" content="{{ request.build_absolute_uri }}" />
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="{% static 'air-datepicker/air-datepicker.css' %}">
|
href="{% static 'air-datepicker/air-datepicker.css' %}">
|
||||||
{% if debug %}
|
|
||||||
<link rel="icon"
|
<link rel="icon"
|
||||||
type="image/svg+xml"
|
type="{{ site_config.get_favicon_mimetype }}"
|
||||||
href="{% static 'images/pdl-64-dev.png' %}">
|
href="{{ site_config.get_favicon_url }}">
|
||||||
{% else %}
|
|
||||||
<link rel="icon"
|
|
||||||
type="image/svg+xml"
|
|
||||||
href="{% static 'images/pdl-64.png' %}">
|
|
||||||
{% endif %}
|
|
||||||
{% load compress %}
|
{% load compress %}
|
||||||
{% compress css %}
|
{% compress css %}
|
||||||
<link type="text/x-scss"
|
<link type="text/x-scss"
|
||||||
@ -108,15 +107,16 @@
|
|||||||
<ul class="menu-droite">
|
<ul class="menu-droite">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'home' %}" aria-label="Retour accueil">
|
<a href="{% url 'home' %}" aria-label="Retour accueil">
|
||||||
<img src="{% static 'images/pdl-64.png' %}" alt="logo pommes de lune" />
|
<img src="{{ site_config.get_favicon_url }}"
|
||||||
|
alt="logo {{ site_config.site_name }}" />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
{% if user.is_authenticated %}{{ user.username }} @{% endif %}
|
{% if user.is_authenticated %}{{ user.username }} @{% endif %}
|
||||||
<a href="{% url 'home' %}" aria-label="Retour accueil">Pommes de lune</a>
|
<a href="{% url 'home' %}" aria-label="Retour accueil">{{ site_config.site_name }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="soustitre">Agenda participatif des sorties culturelles à Clermont-Ferrand et aux environs</div>
|
<div class="soustitre">{{ site_config.site_description }}</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
{% block title %}
|
{% block title %}
|
||||||
{% block og_title %}Statistiques{% endblock %}
|
{% block og_title %}Statistiques{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% load solo_tags %}
|
||||||
{% load cat_extra %}
|
{% load cat_extra %}
|
||||||
{% block entete_header %}
|
{% block entete_header %}
|
||||||
{% css_categories %}
|
{% css_categories %}
|
||||||
@ -15,11 +16,14 @@
|
|||||||
<link rel="stylesheet" href="{% static 'cal-heatmap/cal-heatmap.css' %}">
|
<link rel="stylesheet" href="{% static 'cal-heatmap/cal-heatmap.css' %}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
{% get_solo 'agenda_culturel.SiteConfiguration' as site_config %}
|
||||||
<article>
|
<article>
|
||||||
<header>
|
<header>
|
||||||
<h1>Statistiques</h1>
|
<h1>Statistiques</h1>
|
||||||
</header>
|
</header>
|
||||||
<p>On retrouve sur cette page une synthèse des événements publiés sur l'agenda culturel pommes de lune.</p>
|
<p>
|
||||||
|
On retrouve sur cette page une synthèse des événements publiés sur l'agenda culturel {{ site_config.site_name }}.
|
||||||
|
</p>
|
||||||
<h2>Par date de l'événement</h2>
|
<h2>Par date de l'événement</h2>
|
||||||
<p>Pour chaque date, on retrouve le nombre d'événements qui débutent à cette date (sauf événements récurrents).</p>
|
<p>Pour chaque date, on retrouve le nombre d'événements qui débutent à cette date (sauf événements récurrents).</p>
|
||||||
<div class="large-table">
|
<div class="large-table">
|
||||||
|
@ -101,6 +101,7 @@ from .models import (
|
|||||||
Tag,
|
Tag,
|
||||||
remove_accents,
|
remove_accents,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
|
SiteConfiguration,
|
||||||
)
|
)
|
||||||
from .utils import PlaceGuesser
|
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="")
|
extra += " - " + emoji.replace_emoji(tag, replace="")
|
||||||
|
|
||||||
response["Content-Disposition"] = "attachment; filename={0}{1}{2}".format(
|
response["Content-Disposition"] = "attachment; filename={0}{1}{2}".format(
|
||||||
"Pommes de lune", extra, ".ics"
|
SiteConfiguration.get_solo().site_name, extra, ".ics"
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
@ -50,3 +50,4 @@ requests==2.32.3
|
|||||||
django-cleanup==9.0.0
|
django-cleanup==9.0.0
|
||||||
django-unused-media==0.2.2
|
django-unused-media==0.2.2
|
||||||
django-resized==1.0.3
|
django-resized==1.0.3
|
||||||
|
django-solo==2.4.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user