simplesitesearch 0.0.1.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ __version__ = '0.0.1.dev1'
2
+
3
+
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+ from cms.app_base import CMSApp
3
+ from cms.apphook_pool import apphook_pool
4
+ from django.utils.translation import gettext_lazy as _
5
+
6
+
7
+ @apphook_pool.register
8
+ class SiteSearchApp(CMSApp):
9
+ app_name = "site_search"
10
+ name = _("Site Search")
11
+
12
+ def get_urls(self, page=None, language=None, **kwargs):
13
+ return ["simplesitesearch.urls"]
@@ -0,0 +1,43 @@
1
+ {% load i18n staticfiles cms_tags %}
2
+
3
+ <div class="search__pagination d-flex justify-content-between justify-sm-content-center align-items-center">
4
+ <div class="search__pagination__nav search__pagination__nav--prev">
5
+ {% if prev_link %}
6
+ <a class="search__pagination__nav__item" href="{% url 'site_search:search' %}{{prev_link}}"><i class="fal fa-chevron-left"></i></a>
7
+ {% endif %}
8
+ </div>
9
+ <div class="d-flex search__pagination__links">
10
+ {% for page_link in page_links %}
11
+ <div class="search__pagination__link-container{% ifequal page_link.page current_page %} active{% endifequal %}">
12
+ <a class="search__pagination__link" href="{{ page_link.url }}">{{ page_link.page }}</a>
13
+ </div>
14
+ {% endfor %}
15
+ </div>
16
+ <div class="search__pagination__nav search__pagination__nav--next">
17
+ {% if next_link %}
18
+ <a class="search__pagination__nav__item" href="{% url 'site_search:search' %}{{next_link}}"><i class="fal fa-chevron-right"></i></a>
19
+ {% endif %}
20
+ </div>
21
+ </div>
22
+
23
+ {% comment %}
24
+ <ul class="pagination">
25
+ {% if prev_link %}
26
+ <li>
27
+ <a href="{% url 'site_search:search' %}{{prev_link}}" class="term">«</a>
28
+ </li>
29
+ {% endif %}
30
+
31
+ {% for page_link in page_links %}
32
+ <li{% ifequal page_link.page current_page %} class="active"{% endifequal %}>
33
+ <a href="{{ page_link.url }}" class="page">{{ page_link.page }}</a>
34
+ </li>
35
+ {% endfor %}
36
+
37
+ {% if next_link %}
38
+ <li>
39
+ <a href="{% url 'site_search:search' %}{{next_link}}" class="term">»</a>
40
+ </li>
41
+ {% endif %}
42
+ </ul>
43
+ {% endcomment %}
@@ -0,0 +1,55 @@
1
+ {% extends "base.html" %}
2
+ {% load i18n staticfiles cms_tags %}
3
+
4
+ {% block template_class %}template_search{% endblock %}
5
+
6
+ {% block content %}
7
+ <section id="search" class="section section--nopadding section--nomargin">
8
+ {% if results_count %}
9
+ <div class="search__about-container">
10
+ <div class="search__about d-sm-flex justify-content-between">
11
+ <div class="headings__third-container headings__third-container--noMargin">
12
+ <div class="headings headings__third headings--white">
13
+ <h3>{% trans "Search results for:" %} "{{ query }}"</h3>
14
+ </div>
15
+ </div>
16
+ <div class="text-container">
17
+ <div class="text text--white">
18
+ <p>{{ results_count }} {% trans "result" %}{{ results_count|pluralize }}</p>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ {% endif %}
24
+ </section>
25
+ <section class="section">
26
+ <div class="search__content">
27
+ {% for result in results %}
28
+ <div class="search__content__result">
29
+ <div class="headings__third-container">
30
+ <a class="headings headings__third headings--blue" href="{{result.url}}">{{ result.title|safe }}</a>
31
+ </div>
32
+ <div class="text-container">
33
+ <div class="text text--graydark">
34
+ <p>{{result.highlight|safe}}...</p>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ {% empty %}
39
+ <div class="search__content--empty">
40
+ <div class="headings__third-container">
41
+ <div class="headings headings__third">
42
+ <h3>{% trans "No results" %}</h3>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ {% endfor %}
47
+ </div>
48
+ </section>
49
+ {% if page_links|length > 1 %}
50
+ <section class="section section--nopadding section--nomargin">
51
+ {% include "pagination.html" %}
52
+ </section>
53
+ {% endif %}
54
+
55
+ {% endblock %}
@@ -0,0 +1,7 @@
1
+ from django.urls import include, re_path
2
+
3
+ from . import views
4
+
5
+ urlpatterns = [
6
+ re_path(r'^$', views.SearchResult.as_view(), name='search'),
7
+ ]
@@ -0,0 +1,151 @@
1
+ from math import floor
2
+
3
+ import requests
4
+ from django.conf import settings
5
+ from django.utils.translation import get_language
6
+ from django.views.generic import TemplateView
7
+
8
+
9
+ def get_page_links(pages_count, current_page, term):
10
+
11
+ page_links = []
12
+
13
+ if pages_count > 1:
14
+
15
+ if current_page == 1:
16
+ from_page = 1
17
+ to_page = from_page + 7
18
+ if current_page == pages_count + 1:
19
+ pass
20
+ else:
21
+ from_page = current_page - 4
22
+ to_page = current_page + 5
23
+
24
+ if from_page < 1:
25
+ from_page = 1
26
+
27
+ if to_page > pages_count:
28
+ to_page = pages_count
29
+
30
+ for page in range(from_page, to_page + 1):
31
+ page_link = "?q=%s&page=%s" % (term, page)
32
+
33
+ page_links.append({
34
+ 'page': page,
35
+ 'url': page_link
36
+ })
37
+
38
+ return page_links
39
+
40
+
41
+ def get_prev_next_links(next_page_number, prev_page_number, term):
42
+ next_link = None
43
+ if next_page_number:
44
+ next_link = "?q=%s&page=%s" % (term, next_page_number)
45
+
46
+ prev_link = None
47
+ if prev_page_number:
48
+ prev_link = "?q=%s&page=%s" % (term, prev_page_number)
49
+
50
+ return [prev_link, next_link]
51
+
52
+
53
+ def get_prev_next_page_number(pages_count, current_page):
54
+
55
+ current_page = int(current_page)
56
+ pages_count - int(pages_count)
57
+
58
+ if current_page > 1:
59
+ prev_page_number = current_page - 1
60
+ else:
61
+ prev_page_number = None
62
+
63
+ if current_page < pages_count:
64
+ next_page_number = current_page + 1
65
+ else:
66
+ next_page_number = None
67
+
68
+ return [prev_page_number, next_page_number]
69
+
70
+
71
+ def get_total_pages(total_hits):
72
+ pages_count = floor(total_hits / 10)
73
+
74
+ modulo = total_hits % 10
75
+ if modulo > 0:
76
+ pages_count = pages_count + 1
77
+
78
+ return pages_count
79
+
80
+
81
+ def get_api_re_path(term, current_page):
82
+ base_url = settings.SITE_SEARCH_API_BASE_URL
83
+ site_key = settings.SITE_SEARCH_SITE_KEY
84
+ lang = get_language()
85
+
86
+ return "%s%s?term=%s&lang=%s&page=%s" % (base_url, site_key, term, lang, current_page)
87
+
88
+
89
+ class SearchResult(TemplateView):
90
+
91
+ template_name = "simplesitesearch/search_results.html"
92
+
93
+ def get(self, request, *args, **kwargs):
94
+ context = self.get_context_data(**kwargs)
95
+
96
+ # get Term from url params
97
+ term = request.GET.get('q', None)
98
+ honeypot_message = request.GET.get('message', None)
99
+
100
+ # get current page from url params
101
+ current_page = int(request.GET.get('page', 1))
102
+
103
+ if term and not honeypot_message:
104
+
105
+ term = ' '.join(term.split()[:10])
106
+
107
+ # get api URl depending on current page
108
+ api_url = get_api_re_path(term, current_page)
109
+
110
+ # get results from api
111
+ response = requests.get(api_url, verify=False)
112
+ # convert results to usable json
113
+ try:
114
+ response_data = response.json()
115
+ except:
116
+ response_data = {
117
+ 'total_hits': 0,
118
+ 'hits': []
119
+ }
120
+
121
+ # get pages count
122
+ pages_count = get_total_pages(response_data['total_hits'])
123
+
124
+ # get prev and next page numbers
125
+ prev_page_number, next_page_number = get_prev_next_page_number(pages_count, current_page)
126
+
127
+ # get prev and next btn links
128
+ prev_link, next_link = get_prev_next_links(next_page_number, prev_page_number, term)
129
+
130
+ # get pages links
131
+ page_links = get_page_links(pages_count, current_page, term)
132
+
133
+ context.update({
134
+ 'pages_count': pages_count,
135
+ 'current_page': current_page,
136
+ 'results_count': response_data['total_hits'],
137
+ 'prev_link': prev_link,
138
+ 'next_link': next_link,
139
+ 'page_links': page_links,
140
+ 'results': response_data['hits']
141
+ })
142
+ else:
143
+ context.update({
144
+ 'results': None
145
+ })
146
+
147
+ context.update({
148
+ 'query': term
149
+ })
150
+
151
+ return self.render_to_response(context)
@@ -0,0 +1,256 @@
1
+ Metadata-Version: 2.4
2
+ Name: simplesitesearch
3
+ Version: 0.0.1.dev1
4
+ Summary: Reptile Simple Site Search django app
5
+ Home-page: https://github.com/reptiletech/simplesitesearch
6
+ Author: Reptile Tech
7
+ Author-email: Reptile Tech <flouis@reptile.tech>
8
+ Maintainer-email: Reptile Tech <flouis@reptile.tech>
9
+ License: MIT
10
+ Project-URL: Homepage, https://github.com/reptiletech/simplesitesearch
11
+ Project-URL: Documentation, https://github.com/reptiletech/simplesitesearch#readme
12
+ Project-URL: Repository, https://github.com/reptiletech/simplesitesearch.git
13
+ Project-URL: Bug Tracker, https://github.com/reptiletech/simplesitesearch/issues
14
+ Keywords: django,search,cms,django-cms
15
+ Classifier: Development Status :: 5 - Production/Stable
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.6
21
+ Classifier: Programming Language :: Python :: 3.7
22
+ Classifier: Programming Language :: Python :: 3.8
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Framework :: Django
28
+ Classifier: Framework :: Django :: 2.2
29
+ Classifier: Framework :: Django :: 3.2
30
+ Classifier: Framework :: Django :: 4.0
31
+ Classifier: Framework :: Django :: 4.1
32
+ Classifier: Framework :: Django :: 4.2
33
+ Classifier: Framework :: Django :: 5.0
34
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
35
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
36
+ Requires-Python: >=3.6
37
+ Description-Content-Type: text/markdown
38
+ License-File: LICENSE
39
+ Requires-Dist: Django>=2.2
40
+ Requires-Dist: django-cms>=3.2
41
+ Requires-Dist: requests>=2.22.0
42
+ Dynamic: author
43
+ Dynamic: home-page
44
+ Dynamic: license-file
45
+ Dynamic: requires-python
46
+
47
+ # Simple Site Search
48
+
49
+ A simple Django app for site search functionality with Django CMS integration. This package provides a clean, easy-to-use search interface that can be integrated into Django CMS projects.
50
+
51
+ > **Note**: This is a development version (0.0.1.dev1). The package is still under active development and may have breaking changes in future releases.
52
+
53
+ ## Features
54
+
55
+ - **Django CMS Integration**: Seamlessly integrates with Django CMS as an apphook
56
+ - **Pagination Support**: Built-in pagination for search results
57
+ - **Multi-language Support**: Supports internationalization with Django's i18n framework
58
+ - **Customizable Templates**: Easy to customize search result templates
59
+ - **API Integration**: Connects to external search APIs (like AddSearch)
60
+ - **Responsive Design**: Bootstrap-compatible templates
61
+
62
+ ## Installation
63
+
64
+ Install the package using pip:
65
+
66
+ ```bash
67
+ pip install simplesitesearch
68
+ ```
69
+
70
+ ## Configuration
71
+
72
+ ### 1. Add to INSTALLED_APPS
73
+
74
+ Add `simplesitesearch` to your Django project's `INSTALLED_APPS`:
75
+
76
+ ```python
77
+ INSTALLED_APPS = [
78
+ # ... other apps
79
+ 'simplesitesearch',
80
+ # ... other apps
81
+ ]
82
+ ```
83
+
84
+ ### 2. Required Settings
85
+
86
+ Add the following settings to your Django settings file:
87
+
88
+ ```python
89
+ # Search API Configuration
90
+ SITE_SEARCH_API_BASE_URL = "https://search.rt5.ca/reptile_search/api/search/"
91
+ SITE_SEARCH_SITE_KEY = "your-site-key-here"
92
+ SITE_SEARCH_API_KEY = "your-api-key-here" # Optional, if required by your API
93
+ ```
94
+
95
+ ### 3. URL Configuration
96
+
97
+ Include the app's URLs in your main `urls.py`:
98
+
99
+ ```python
100
+ from django.urls import path, include
101
+
102
+ urlpatterns = [
103
+ # ... other URL patterns
104
+ path('search/', include('simplesitesearch.urls')),
105
+ # ... other URL patterns
106
+ ]
107
+ ```
108
+
109
+ ## Django CMS Integration
110
+
111
+ ### 1. Create a Search Page
112
+
113
+ 1. Log into your Django CMS admin
114
+ 2. Go to **Django CMS** > **Pages**
115
+ 3. Create a new page named "Search"
116
+ 4. Translate the title and slug in all languages
117
+ 5. Save and continue editing
118
+
119
+ ### 2. Configure the Page
120
+
121
+ 1. Go to **Advanced settings** of the search page
122
+ 2. Set the **ID** to `'search'`
123
+ 3. Set **APPLICATION** to "Site Search"
124
+ 4. Save the page
125
+ 5. Remove the page from the menu (uncheck "menu" in the table)
126
+ 6. Publish the page in all languages
127
+
128
+ ### 3. Access the Search
129
+
130
+ Your search functionality will be available at the URL you configured for the search page.
131
+
132
+ ## Usage
133
+
134
+ ### Basic Search
135
+
136
+ The search form accepts a `q` parameter for the search term:
137
+
138
+ ```
139
+ /search/?q=your+search+term
140
+ ```
141
+
142
+ ### Pagination
143
+
144
+ The search results support pagination with a `page` parameter:
145
+
146
+ ```
147
+ /search/?q=your+search+term&page=2
148
+ ```
149
+
150
+ ### Honeypot Protection
151
+
152
+ The search includes basic honeypot protection. If a `message` parameter is present, the search will not execute.
153
+
154
+ ## Customization
155
+
156
+ ### Templates
157
+
158
+ The package includes two main templates:
159
+
160
+ - `simplesitesearch/search_results.html` - Main search results template
161
+ - `simplesitesearch/pagination.html` - Pagination template
162
+
163
+ #### Template Customization
164
+
165
+ You can override these templates in your project by creating templates with the same names in your template directory. The templates are designed to be easily customizable:
166
+
167
+ **Template Include Paths:**
168
+ - `simplesitesearch/search_results.html` - Main search results page
169
+ - `simplesitesearch/pagination.html` - Pagination component (included in search_results.html)
170
+
171
+ **To customize templates:**
172
+ 1. Create a `templates/simplesitesearch/` directory in your Django project
173
+ 2. Copy the template files from the package and modify them as needed
174
+ 3. Your custom templates will override the package defaults
175
+
176
+ **Example template structure:**
177
+ ```
178
+ your_project/
179
+ ├── templates/
180
+ │ └── simplesitesearch/
181
+ │ ├── search_results.html # Your custom search results template
182
+ │ └── pagination.html # Your custom pagination template
183
+ ```
184
+
185
+ ### Styling
186
+
187
+ The templates use Bootstrap classes and can be easily customized with CSS. The main CSS classes used are:
188
+
189
+ - `.pagination` - Pagination container
190
+ - `.search_query` - Search query display
191
+ - `.search_results` - Results count display
192
+ - `.wrapper_single_result` - Individual result container
193
+
194
+ ## API Response Format
195
+
196
+ The search expects the API to return JSON in the following format:
197
+
198
+ ```json
199
+ {
200
+ "total_hits": 42,
201
+ "hits": [
202
+ {
203
+ "title": "Page Title",
204
+ "url": "https://example.com/page/",
205
+ "highlight": "Search term highlighted content..."
206
+ }
207
+ ]
208
+ }
209
+ ```
210
+
211
+ ## Requirements
212
+
213
+ - Python 3.6+
214
+ - Django 2.2+
215
+ - django-cms 3.2+
216
+ - requests 2.22.0+
217
+
218
+ ## Development
219
+
220
+ ### Local Development
221
+
222
+ 1. Clone the repository
223
+ 2. Install in development mode:
224
+ ```bash
225
+ pip install -e .
226
+ ```
227
+
228
+ ### Testing
229
+
230
+ Run the tests with:
231
+
232
+ ```bash
233
+ python manage.py test simplesitesearch
234
+ ```
235
+
236
+ ## License
237
+
238
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
239
+
240
+ ## Support
241
+
242
+ For support and questions, please open an issue on the [GitHub repository](https://github.com/yourusername/simplesitesearch/issues).
243
+
244
+ ## Changelog
245
+
246
+ ### 0.0.1.dev1
247
+ - Initial development release
248
+ - Django CMS integration
249
+ - Pagination support
250
+ - Multi-language support
251
+ - Basic search functionality
252
+ - Template customization support
253
+ - Support for Python 3.6+ and Django 2.2+
254
+ - Updated API endpoint to use Reptile Search API
255
+
256
+
@@ -0,0 +1,11 @@
1
+ simplesitesearch/__init__.py,sha256=259yVYoZ0qRnvmlzBLwt-nqou6DtFCC-MRKbyW3LMnk,29
2
+ simplesitesearch/cms_apps.py,sha256=Zp48MmxavV-s-7XbfkJmeYkPsFtOz8vsicgnWZT9Vz8,366
3
+ simplesitesearch/urls.py,sha256=7M7rcMlglmVnVOOBUEmtlaH7BA7W2f3-7xB8hpiLm3Y,146
4
+ simplesitesearch/views.py,sha256=FTKYdbh0MGEhjoGjYaHTKIPRxsBfO-CSh1I5S_nbCQw,4102
5
+ simplesitesearch/templates/simplesitesearch/pagination.html,sha256=u3XrAaEIK922oCXTreN1cmzW6z3C8FSwu_e5xeZyHBM,1644
6
+ simplesitesearch/templates/simplesitesearch/search_results.html,sha256=_HQV1i3vNOtJph83NDHvS9QozSceCdYIbI_kraltWxk,2130
7
+ simplesitesearch-0.0.1.dev1.dist-info/licenses/LICENSE,sha256=dRZHhCf5a7ZSLSofyQQJJidW9mQ-uX3dwnph0tqrkhU,1077
8
+ simplesitesearch-0.0.1.dev1.dist-info/METADATA,sha256=lEr2Ix_m1vD9pshRjmh8bDeNt0DD-rjrGCxtHOlD0Sw,7198
9
+ simplesitesearch-0.0.1.dev1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ simplesitesearch-0.0.1.dev1.dist-info/top_level.txt,sha256=MKqY_-x--5g-Toif0DEYAoH8Wo71JTNj9pYLbzb778M,17
11
+ simplesitesearch-0.0.1.dev1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Simple Site Search
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+
@@ -0,0 +1 @@
1
+ simplesitesearch