simplesitesearch 1.0.0__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 @@
1
+ __version__ = '1.0.0'
@@ -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,42 @@
1
+ {% load i18n static cms_tags %}
2
+
3
+
4
+ <ul class="pagination">
5
+ {% if prev_link %}
6
+ <li>
7
+ <a class="term" href="{% url 'site_search:search' %}{{prev_link}}">{% trans "Previous" %}</a>
8
+ </li>
9
+ {% endif %}
10
+ {% for page_link in page_links %}
11
+ <li {% if page_link.page == current_page %}class="active"{% endif %}>
12
+ <a class="page" href="{{ page_link.url }}">{{ page_link.page }}</a>
13
+ </li>
14
+ {% endfor %}
15
+ {% if next_link %}
16
+ <li>
17
+ <a class="term" href="{% url 'site_search:search' %}{{next_link}}">{% trans "Next" %}</a>
18
+ </li>
19
+ {% endif %}
20
+ </ul>
21
+
22
+ {% comment %}
23
+ <ul class="pagination">
24
+ {% if prev_link %}
25
+ <li>
26
+ <a href="{% url 'site_search:search' %}{{prev_link}}" class="term">«</a>
27
+ </li>
28
+ {% endif %}
29
+
30
+ {% for page_link in page_links %}
31
+ <li{% if page_link.page == current_page %} class="active"{% endif %}>
32
+ <a href="{{ page_link.url }}" class="page">{{ page_link.page }}</a>
33
+ </li>
34
+ {% endfor %}
35
+
36
+ {% if next_link %}
37
+ <li>
38
+ <a href="{% url 'site_search:search' %}{{next_link}}" class="term">»</a>
39
+ </li>
40
+ {% endif %}
41
+ </ul>
42
+ {% endcomment %}
@@ -0,0 +1,48 @@
1
+ {% extends "food_service/content_fullwidth.html" %}
2
+ {% load i18n static cms_tags %}
3
+
4
+ {% block template_class %}template_search{% endblock %}
5
+ {% block body_class_search %}page_add_search{% endblock %}
6
+
7
+ {% block container %}
8
+ <div class="container white_bg">
9
+ <div class="block">
10
+ <div class="row">
11
+ <div class="col-xs-12">
12
+ {% if results_count %}
13
+ <div class="search_query titles">
14
+ {% trans "Search results for:" %} "{{ query }}"
15
+ </div>
16
+
17
+ <div class="search_results dates">
18
+ {% blocktrans count counter=results_count %}About {{ counter }} result{% plural %}About {{ counter }} results{% endblocktrans %}
19
+ </div>
20
+ {% endif %}
21
+ </div>
22
+ </div>
23
+ {% for result in results %}
24
+ <div class="row wrapper_single_result">
25
+ <div class="col-xs-12">
26
+ <a class="subtitles" href="{{result.url}}">{{ result.title|safe }}</a>
27
+ <p>{{result.highlight|safe}}...</p>
28
+ </div>
29
+ </div>
30
+ {% empty %}
31
+ <div class="col-xs-12 guttered">
32
+ <p class="titles">{% trans "No results" %}</p>
33
+ </div>
34
+ {% endfor %}
35
+
36
+ {% if page_links|length > 1 %}
37
+ <div class="row">
38
+ <div class="col-xs-12 guttered">
39
+ <div class="wrapper_paginator text-center">
40
+ {% include "simplesitesearch/pagination.html" %}
41
+ </div>
42
+ </div>
43
+ </div>
44
+ {% endif %}
45
+ </div>
46
+ </div>
47
+
48
+ {% 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,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: simplesitesearch
3
+ Version: 1.0.0
4
+ Summary: A simple Django app for site search functionality with Django CMS integration
5
+ Home-page: https://github.com/yourusername/simplesitesearch
6
+ Author: Your Name
7
+ Author-email: Your Name <your.email@example.com>
8
+ Maintainer-email: Your Name <your.email@example.com>
9
+ License: MIT
10
+ Project-URL: Homepage, https://github.com/yourusername/simplesitesearch
11
+ Project-URL: Documentation, https://github.com/yourusername/simplesitesearch#readme
12
+ Project-URL: Repository, https://github.com/yourusername/simplesitesearch.git
13
+ Project-URL: Bug Tracker, https://github.com/yourusername/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.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Framework :: Django
26
+ Classifier: Framework :: Django :: 3.2
27
+ Classifier: Framework :: Django :: 4.0
28
+ Classifier: Framework :: Django :: 4.1
29
+ Classifier: Framework :: Django :: 4.2
30
+ Classifier: Framework :: Django :: 5.0
31
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
32
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
33
+ Requires-Python: >=3.8
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: Django>=3.2
37
+ Requires-Dist: django-cms>=3.2
38
+ Requires-Dist: requests>=2.25.0
39
+ Dynamic: author
40
+ Dynamic: home-page
41
+ Dynamic: license-file
42
+ Dynamic: requires-python
43
+
44
+ # Simple Site Search
45
+
46
+ 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.
47
+
48
+ ## Features
49
+
50
+ - **Django CMS Integration**: Seamlessly integrates with Django CMS as an apphook
51
+ - **Pagination Support**: Built-in pagination for search results
52
+ - **Multi-language Support**: Supports internationalization with Django's i18n framework
53
+ - **Customizable Templates**: Easy to customize search result templates
54
+ - **API Integration**: Connects to external search APIs (like AddSearch)
55
+ - **Responsive Design**: Bootstrap-compatible templates
56
+
57
+ ## Installation
58
+
59
+ Install the package using pip:
60
+
61
+ ```bash
62
+ pip install simplesitesearch
63
+ ```
64
+
65
+ ## Configuration
66
+
67
+ ### 1. Add to INSTALLED_APPS
68
+
69
+ Add `simplesitesearch` to your Django project's `INSTALLED_APPS`:
70
+
71
+ ```python
72
+ INSTALLED_APPS = [
73
+ # ... other apps
74
+ 'simplesitesearch',
75
+ # ... other apps
76
+ ]
77
+ ```
78
+
79
+ ### 2. Required Settings
80
+
81
+ Add the following settings to your Django settings file:
82
+
83
+ ```python
84
+ # Search API Configuration
85
+ SITE_SEARCH_API_BASE_URL = "https://api.addsearch.com/v1/search/"
86
+ SITE_SEARCH_SITE_KEY = "your-site-key-here"
87
+ SITE_SEARCH_API_KEY = "your-api-key-here" # Optional, if required by your API
88
+ ```
89
+
90
+ ### 3. URL Configuration
91
+
92
+ Include the app's URLs in your main `urls.py`:
93
+
94
+ ```python
95
+ from django.urls import path, include
96
+
97
+ urlpatterns = [
98
+ # ... other URL patterns
99
+ path('search/', include('simplesitesearch.urls')),
100
+ # ... other URL patterns
101
+ ]
102
+ ```
103
+
104
+ ## Django CMS Integration
105
+
106
+ ### 1. Create a Search Page
107
+
108
+ 1. Log into your Django CMS admin
109
+ 2. Go to **Django CMS** > **Pages**
110
+ 3. Create a new page named "Search"
111
+ 4. Translate the title and slug in all languages
112
+ 5. Save and continue editing
113
+
114
+ ### 2. Configure the Page
115
+
116
+ 1. Go to **Advanced settings** of the search page
117
+ 2. Set the **ID** to `'search'`
118
+ 3. Set **APPLICATION** to "Site Search"
119
+ 4. Save the page
120
+ 5. Remove the page from the menu (uncheck "menu" in the table)
121
+ 6. Publish the page in all languages
122
+
123
+ ### 3. Access the Search
124
+
125
+ Your search functionality will be available at the URL you configured for the search page.
126
+
127
+ ## Usage
128
+
129
+ ### Basic Search
130
+
131
+ The search form accepts a `q` parameter for the search term:
132
+
133
+ ```
134
+ /search/?q=your+search+term
135
+ ```
136
+
137
+ ### Pagination
138
+
139
+ The search results support pagination with a `page` parameter:
140
+
141
+ ```
142
+ /search/?q=your+search+term&page=2
143
+ ```
144
+
145
+ ### Honeypot Protection
146
+
147
+ The search includes basic honeypot protection. If a `message` parameter is present, the search will not execute.
148
+
149
+ ## Customization
150
+
151
+ ### Templates
152
+
153
+ The package includes two main templates:
154
+
155
+ - `simplesitesearch/search_results.html` - Main search results template
156
+ - `simplesitesearch/pagination.html` - Pagination template
157
+
158
+ You can override these templates in your project by creating templates with the same names in your template directory.
159
+
160
+ ### Styling
161
+
162
+ The templates use Bootstrap classes and can be easily customized with CSS. The main CSS classes used are:
163
+
164
+ - `.pagination` - Pagination container
165
+ - `.search_query` - Search query display
166
+ - `.search_results` - Results count display
167
+ - `.wrapper_single_result` - Individual result container
168
+
169
+ ## API Response Format
170
+
171
+ The search expects the API to return JSON in the following format:
172
+
173
+ ```json
174
+ {
175
+ "total_hits": 42,
176
+ "hits": [
177
+ {
178
+ "title": "Page Title",
179
+ "url": "https://example.com/page/",
180
+ "highlight": "Search term highlighted content..."
181
+ }
182
+ ]
183
+ }
184
+ ```
185
+
186
+ ## Requirements
187
+
188
+ - Python 3.8+
189
+ - Django 3.2+
190
+ - django-cms 3.2+
191
+ - requests 2.25.0+
192
+
193
+ ## Development
194
+
195
+ ### Local Development
196
+
197
+ 1. Clone the repository
198
+ 2. Install in development mode:
199
+ ```bash
200
+ pip install -e .
201
+ ```
202
+
203
+ ### Testing
204
+
205
+ Run the tests with:
206
+
207
+ ```bash
208
+ python manage.py test simplesitesearch
209
+ ```
210
+
211
+ ## License
212
+
213
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
214
+
215
+ ## Contributing
216
+
217
+ 1. Fork the repository
218
+ 2. Create a feature branch
219
+ 3. Make your changes
220
+ 4. Add tests for your changes
221
+ 5. Submit a pull request
222
+
223
+ ## Support
224
+
225
+ For support and questions, please open an issue on the [GitHub repository](https://github.com/yourusername/simplesitesearch/issues).
226
+
227
+ ## Changelog
228
+
229
+ ### 1.0.0
230
+ - Initial release
231
+ - Django CMS integration
232
+ - Pagination support
233
+ - Multi-language support
234
+ - Basic search functionality
@@ -0,0 +1,11 @@
1
+ simplesitesearch/__init__.py,sha256=RsZjRjMprNcDm97wqRRSk6rTLgTX8N0GyicZyZ8OsBQ,22
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=uNkWxluZW8UuId3X17NW_uerZHxDBGwlMvv_nuToRbU,1237
6
+ simplesitesearch/templates/simplesitesearch/search_results.html,sha256=97YlWSu3mC9pZ78FTdO_MSLAJWcFBW2xf08iG36e2wI,1811
7
+ simplesitesearch-1.0.0.dist-info/licenses/LICENSE,sha256=-z21ntbC3ZCLQW0EciNYecswDeD9NQQL3Q5MZxXKLG4,1075
8
+ simplesitesearch-1.0.0.dist-info/METADATA,sha256=1I8DbD_Ccw-espZmfZd-bY9h1vexiYtXuM3ZNkyWqrU,6160
9
+ simplesitesearch-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ simplesitesearch-1.0.0.dist-info/top_level.txt,sha256=MKqY_-x--5g-Toif0DEYAoH8Wo71JTNj9pYLbzb778M,17
11
+ simplesitesearch-1.0.0.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,21 @@
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.
@@ -0,0 +1 @@
1
+ simplesitesearch