10000 docs: add documentation for search (#7972) · django-cms/django-cms@40b0c9f · GitHub
[go: up one dir, main page]

Skip to content

Commit 40b0c9f

Browse files
docs: add documentation for search (#7972)
* docs: how to implement search * fix: simplify index example even further and fix small bug * docs: remove djangocms-versioning filter Co-authored-by: Fabian Braun <fsbraun@gmx.de> * chore: fix codespell issue --------- Co-authored-by: Fabian Braun <fsbraun@gmx.de>
1 parent b4f54a5 commit 40b0c9f

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

docs/explanation/publishing.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ details please consult the `djangocms-versioning documentation
2020
Also, while this section focuses on pages, djangocms-versioning can lend its versioning
2121
capabilities to other objects, too, e.g., aliases as defined in djangocms-alias.
2222

23+
.. _version_states:
24+
2325
Version states
2426
--------------
2527

docs/explanation/searchdocs.rst

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,128 @@
11
Search and django CMS
22
=====================
3+
4+
.. seealso::
5+
6+
- :ref:`Version States <version_states>`
7+
- `djangocms-versioning <https://github.com/django-cms/djangocms-versioning>`_
8+
- `django-haystack <https://github.com/django-haystack/django-haystack>`_
9+
10+
If you already have a background in django CMS and are coming from the 3.x days, you may
11+
be familiar with the package ``aldryn-search`` which was the recommended way for setting up
12+
search inside your django CMS project. However, with the deprecation of it and the new
13+
versioning primitives in django CMS 4.x being incompatible with it, you may wonder where to
14+
go from here.
15+
16+
To keep it simple, you can install an external package that handles implementing the search
17+
index for you. There are multiple options, such as
18+
19+
* `djangocms-aldryn-search <https://github.com/CZ-NIC/djangocms-aldryn-search>`_
20+
* `djangocms-haystack <https://github.com/Lfd4/djangocms-haystack>`_
21+
* ... and others
22+
23+
The idea is that we implement the search index just as we would for normal Django models,
24+
e.g. use an external library to handle the indexing (``django-haystack`` in the above examples)
25+
and just implement the logic that builds the querysets and filters the languages depending on
26+
what index is currently active. ``django-haystack`` exposes many helpful utilities for
27+
interacting with the indexes and return the appropriate results for indexing.
28+
29+
To get an idea on how this works, feel free to look at the code of the above projects.
30+
A very simple index could look something like this:
31+
32+
.. code-block:: python
33+
:emphasize-lines: 3
34+
35+
from cms.models import PageContent
36+
from django.db import models
37+
from haystack import indexes
38+
39+
40+
class PageContentIndex(indexes.SearchIndex, indexes.Indexable):
41+
text = indexes.CharField(document=True, use_template=False)
42+
title = indexes.CharField(indexed=False, stored=True)
43+
url = indexes.CharField(indexed=False, stored=True)
44+
45+
def get_model(self):
46+
return PageContent
47+
48+
def index_queryset(self, using=None) -> models.QuerySet:
49+
return self.get_model().objects.filter(language=using)
50+
51+
def prepare(self, instance: PageContent) -> dict:
52+
self.prepared_data = super().prepare(instance)
53+
self.prepared_data["url"] = instance.page.get_absolute_url()
54+
self.prepared_data["title"] = instance.title
55+
self.prepared_data["text"] = (
56+
self.prepared_data["title"] + (instance.meta_description or "")
57+
)
58+
return self.prepared_data
59+
60+
.. hint::
61+
Your index should be placed inside a ``search_indexes.py`` in one of your
62+
``INSTALLED_APPS``!
63+
64+
The above snippet uses the standard ``text`` field that is recommended by
65+
``django-haystack`` to store all the indexable content. There is also a
66+
separate field for the title because you may want to display it as a heading
67+
in your search result, and a field for the URL so you can link to the pages.
68+
69+
The indexed content here is *not* using a template (which is one of the options
70+
to compose fields into an indexable field) but rather concatenates it manually
71+
using the ``prepare`` method which gets called by ``django-haystack`` to prepare data
72+
before the indexing starts.
73+
74+
As you can see in the ``index_queryset`` method, we only return those ``PageContent``
75+
instances that are ``published`` and have a language matching the currently used
76+
Haystack connection key.
77+
78+
The ``PageContent`` then get passed into the ``prepare`` method one by one, so we can
79+
use the ``instance.page`` attribute to get the page meta description and use it as
80+
indexable text as well as the title of the current ``PageContent`` version.
81+
82+
Finally, you need to set your ``HAYSTACK_CONNECTIONS`` to contain a default key as
83+
well as **any language that you want to be indexed** as additional keys.
84+
You could also use different backends for your languages as well, this is up to you
85+
and how you want to configure your haystack installation.
86+
An example could look somewhat like this:
87+
88+
.. code-block:: python
89+
:emphasize-lines: 3
90+
91+
...
92+
93+
HAYSTACK_CONNECTIONS = {
94+
'default': {
95+
"ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
96+
"PATH": os.path.join(ROOT_DIR, "search_index", "whoosh_index_default"),
97+
},
98+
"en": {
99+
"ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
100+
"PATH": os.path.join(ROOT_DIR, "search_index", "whoosh_index_en"),
101+
},
102+
"de": {
103+
"ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
104+
"PATH": os.path.join(ROOT_DIR, "search_index", "whoosh_index_de"),
105+
}
106+
}
107+
108+
...
109+
110+
.. hint::
111+
This should be configured in your projects ``settings.py``!
112+
113+
Now run ``python manage.py rebuild_index`` to start building your index. Depending on
114+
what backend you chose you should now see your index at the configured location.
115+
116+
You can inspect your index using a ``SearchQuerySet``:
117+
118+
.. code-block:: python
119+
:emphasize-lines: 3
120+
121+
from haystack.query import SearchQuerySet
122+
123+
qs = SearchQuerySet(using="<your haystack connection alias / language key>")
124+
for result in qs.all():
125+
print(result.text)
126+
127+
Now it's up to you to add custom indexes to your own models, build views for your
128+
``SearchQuerySet`` to implement a search form and much more.

0 commit comments

Comments
 (0)
0