Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mettre en place une page de recherche plein texte #79

Merged
merged 3 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,6 @@ dmypy.json
# VSCode
.VSCode
.vscode/

# Project-specific stuff
cron.json
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
postdeploy: python manage.py migrate
postdeploy: python manage.py migrate && python manage.py update_index
web: gunicorn config.wsgi --log-file -
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,18 @@ Vous pouvez également générer un rapport sur la couverture de tests :
```sh
coverage run manage.py test --settings config.settings_test
```

## Indexation des contenus
Les contenus des pages sont indexés pour la recherche par un script `python manage.py update_index` (cf. [documentation de Wagtail](https://docs.wagtail.org/en/stable/topics/search/indexing.html))

### Scalingo
Le script est lancé automatiquement après les déploiements sur Scalingo.

Il est recommandé de procéder à une nouvelle indexation une fois par semaine, en renommant le fichier `cron.json.example` en `cron.json` (cf. [documentation de Scalingo](https://doc.scalingo.com/platform/app/task-scheduling/scalingo-scheduler))

### Autres déploiements
Il est recommandé de faire de même pour les déploiements sur d’autres plateformes, en ajoutant une ligne à la crontab de l’utilisateur avec lequel tourne le site :

```
0 3 * * SUN python manage.py update_index
```
17 changes: 17 additions & 0 deletions content_manager/migrations/0011_cmsdsfrconfig_search_bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2024-01-15 11:19

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("content_manager", "0010_alter_contentpage_body"),
]

operations = [
migrations.AddField(
model_name="cmsdsfrconfig",
name="search_bar",
field=models.BooleanField(default=False, verbose_name="Barre de recherche dans l’en-tête"),
),
]
2 changes: 2 additions & 0 deletions content_manager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class Meta:
help_text="Balises HTML autorisés",
)

search_bar = models.BooleanField("Barre de recherche dans l’en-tête", default=False)
theme_modale_button = models.BooleanField("Choix du thème clair/sombre", default=False)
mourning = models.BooleanField("Mise en berne", default=False)

Expand All @@ -173,6 +174,7 @@ class Meta:
FieldPanel("site_title"),
FieldPanel("site_tagline"),
FieldPanel("footer_description"),
FieldPanel("search_bar"),
FieldPanel("mourning"),
FieldPanel("theme_modale_button"),
]
16 changes: 9 additions & 7 deletions content_manager/templates/content_manager/content_page.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{% extends 'base.html' %}
{% extends "base.html" %}

{% load static dsfr_tags wagtailcore_tags wagtailimages_tags %}

{% block title %}
<title>{{ page.seo_title|default:page.title }} — {{ settings.content_manager.CmsDsfrConfig.site_title }}</title>
{% endblock title %}

{% if page.search_description %}
{% block description %}
<meta name="description" content="{{ page.search_description }}" />
{% endblock description %}
{% endif %}

{% block content %}
{# Display Django message info from previous form #}
{% if messages %}
Expand Down Expand Up @@ -37,9 +41,7 @@
{% for block in page.body %}
{% if block.block_type == 'hero' %}
{% include "content_manager/blocks/hero.html" %}
<div class="fr-container">
{% include "content_manager/blocks/breadcrumbs.html" %}
</div>
<div class="fr-container">{% include "content_manager/blocks/breadcrumbs.html" %}</div>
{% elif block.block_type == 'title' %}
<div class="fr-container fr-mt-6w">
<div class="fr-grid-row fr-grid-row--gutters">
Expand Down Expand Up @@ -69,17 +71,17 @@ <h1 class="fr-display--sm">{{ block.value.title }}</h1>
{% elif block.block_type == 'image' %}
<div class="fr-container fr-my-3w">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12">{% include "content_manager/blocks/image.html" %}</div>
<div class="fr-col-12">{% include "content_manager/blocks/image.html" %}</div>
</div>
</div>
{% elif block.block_type == 'video' %}
<div class="fr-container fr-my-3w">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12 fr-col-offset-md-2 fr-col-md-8">{% include "content_manager/blocks/video.html" %}</div>
<div class="fr-col-12 fr-col-offset-md-2 fr-col-md-8">{% include "content_manager/blocks/video.html" %}</div>
</div>
</div>
{% elif block.block_type == 'multicolumns' %}
{% include "content_manager/blocks/multicolumns.html" %}
{% include "content_manager/blocks/multicolumns.html" %}
{% elif block.block_type == 'paragraph' %}
<div class="fr-container">
<div class="fr-grid-row fr-grid-row--gutters">
Expand Down
66 changes: 66 additions & 0 deletions content_manager/templates/content_manager/search_results.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{% extends "base.html" %}

{% load static dsfr_tags wagtailcore_tags wagtailimages_tags %}

{% block title %}
<title>
{% if object_list.count %}
{{ object_list.count }} résultat{{ object_list.count|pluralize }}
{% else %}
Aucun résultat
{% endif %}
pour la recherche « {{ query }} » — {{ settings.content_manager.CmsDsfrConfig.site_title }}</title>
{% endblock title %}

{% if page.search_description %}
{% block description %}
<meta name="description"
content="{% if object_list.count %} {{ object_list.count }} résultat{{ object_list.count|pluralize }} {% else %} Aucun résultat {% endif %} pour la recherche « {{ query }} »" />
{% endblock description %}
{% endif %}

{% block content %}
<div class="fr-container fr-my-4w">
<h1>
{% if object_list.count %}
{{ object_list.count }} résultat{{ object_list.count|pluralize }}
{% else %}
Aucun résultat
{% endif %}
pour la recherche « {{ query }} »
</h1>
{% if object_list.count %}
<ol>
{% for result in object_list %}
<li>
<h2 class="fr-h4">
<a href="{% pageurl result %}">{{ result }}</a>
</h2>
{% if result.search_description %}<p>{{ result.search_description|safe }}</p>{% endif %}

</li>
{% endfor %}
</ol>
{% else %}
<div class="fr-my-7w fr-mt-md-12w fr-mb-md-10w fr-grid-row fr-grid-row--gutters fr-grid-row--middle fr-grid-row--center">
<div class="fr-py-0 fr-col-12 fr-col-md-6">
<h2 class="fr-mb-3w">Nous n’avons trouvé aucun contenu correspondant à votre recherche.</h2>
<p>Pour continuer votre visite, vous pouvez consulter notre page d’accueil.</p>
<ul class="fr-btns-group fr-btns-group--inline-md">
<li>
<a class="fr-btn" href="/">Page d’accueil</a>
</li>
</ul>
</div>
<div class="fr-col-12 fr-col-md-3 fr-col-offset-md-1 fr-px-6w fr-px-md-0 fr-py-0">
<img src="{% static 'dsfr/dist/artwork/pictograms/digital/search.svg' %}"
class="fr-responsive-img"
alt=""
width="300"
height="300" />
</div>
</div>
{% endif %}
</div>

{% endblock content %}
3 changes: 3 additions & 0 deletions content_manager/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as wagtaildocs_urls

from content_manager.views import SearchResultsView


urlpatterns = [
path("cms-admin/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("recherche/", SearchResultsView.as_view(), name="cms_search"),
path("", include(wagtail_urls)),
]
22 changes: 22 additions & 0 deletions content_manager/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.views.generic import ListView

from content_manager.models import ContentPage


class SearchResultsView(ListView):
model = ContentPage
template_name = "content_manager/search_results.html"

def get_queryset(self):
query = self.request.GET.get("q", None)
if query:
object_list = ContentPage.objects.live().search(query)

else:
object_list = ContentPage.objects.none()
return object_list

def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context["query"] = self.request.GET.get("q")
return context
7 changes: 7 additions & 0 deletions cron.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"jobs": [
{
"command": "0 3 * * SUN python manage.py update_index"
}
]
}
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ readme = "README.md"
python = "^3.10"
django = "^4.2.7"
wagtail = "^5.2.1"
django-dsfr = "^0.17.0"
django-dsfr = "^0.17.1"
psycopg2-binary = "^2.9.9"
python-dotenv = "^1.0.0"
dj-database-url = "^2.1.0"
Expand Down
18 changes: 11 additions & 7 deletions templates/404.html
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
{% extends 'base.html' %}
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="fr-container">
<div class="fr-my-7w fr-mt-md-12w fr-mb-md-10w fr-grid-row fr-grid-row--gutters fr-grid-row--middle fr-grid-row--center">
<div class="fr-py-0 fr-col-12 fr-col-md-6">
<h1>Page non trouvée</h1>
<p class="fr-text--sm fr-mb-3w">Erreur 404</p>
<p class="fr-text--lead fr-mb-3w">La page que vous cherchez est introuvable. Excusez-nous pour la gène occasionnée.</p>
<p class="fr-text--lead fr-mb-3w">
La page que vous cherchez est introuvable. Veuillez nous excuser pour la gène occasionnée.
</p>
<p class="fr-text--sm fr-mb-5w">
Si vous avez tapé l'adresse web dans le navigateur, vérifiez qu'elle est correcte. La page n’est peut-être plus disponible.
<br/>
Dans ce cas, pour continuer votre visite vous pouvez consulter notre page d’accueil.
Si vous avez tapé ladresse web dans le navigateur, vérifiez quelle est correcte. La page n’est peut-être plus disponible.
<br />
Dans ce cas, pour continuer votre visite, vous pouvez consulter notre page d’accueil.
</p>
<ul class="fr-btns-group fr-btns-group--inline-md">
<li>
<a class="fr-btn" href="/">Page d'accueil</a>
<a class="fr-btn" href="/">Page daccueil</a>
</li>
</ul>
</div>
<div class="fr-col-12 fr-col-md-3 fr-col-offset-md-1 fr-px-6w fr-px-md-0 fr-py-0">
<img src="{% static 'artwork/technical-error.svg' %}"
class="fr-responsive-img"
alt=""/>
alt=""
width="300"
height="300" />
</div>
</div>
</div>
Expand Down
8 changes: 5 additions & 3 deletions templates/500.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends 'base.html' %}
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="fr-container">
Expand All @@ -12,14 +12,16 @@ <h1>Erreur inattendue</h1>
</p>
<ul class="fr-btns-group fr-btns-group--inline-md">
<li>
<a class="fr-btn" href="/">Page d'accueil</a>
<a class="fr-btn" href="/">Page daccueil</a>
</li>
</ul>
</div>
<div class="fr-col-12 fr-col-md-3 fr-col-offset-md-1 fr-px-6w fr-px-md-0 fr-py-0">
<img src="{% static 'artwork/technical-error.svg' %}"
class="fr-responsive-img"
alt=""/>
alt=""
width="300"
height="300" />
</div>
</div>
</div>
Expand Down
23 changes: 23 additions & 0 deletions templates/blocks/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@
{% flat_menu handle="header_tools" template="menus/custom_flat_menu.html" %}
{% endblock header_tools %}

{% block header_search %}
{% if settings.content_manager.CmsDsfrConfig.search_bar %}
<div class="fr-header__search fr-modal" id="modal-search">
<div class="fr-container fr-container-lg--fluid">
<button class="fr-btn--close fr-btn"
aria-controls="modal-search"
title="Fermer">Fermer</button>
<form action="{% url 'cms_search' %}" method="get">
<div class="fr-search-bar" id="search-bar" role="search">
<label class="fr-label" for="search-bar-input">Rechercher</label>
<input class="fr-input"
placeholder="Rechercher"
type="search"
id="query"
name="q">
<button class="fr-btn" title="Rechercher">Rechercher</button>
</div>
</form>
</div>
</div>
{% endif %}
{% endblock header_search %}

{# Leave burger_menu and main_menu blocks empty if the main menu is not used #}
{# block burger_menu #}
{# endblock burger_menu #}
Expand Down