Metadata-Version: 2.4
Name: ocyan.compat.django-oscar-elasticsearch
Version: 3.0.2
Summary: MandelBlog compatibility distribution for Django Oscar Elasticsearch
Author-email: MandelBlog <info@mandelblog.com>
License: Copyright (c) 2011-present Tangent Communications PLC and individual contributors.
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without modification,
        are permitted provided that the following conditions are met:
        
            1. Redistributions of source code must retain the above copyright notice,
               this list of conditions and the following disclaimer.
           
            2. Redistributions in binary form must reproduce the above copyright
               notice, this list of conditions and the following disclaimer in the
               documentation and/or other materials provided with the distribution.
        
            3. Neither the name of Tangent Communications PLC nor the names of its contributors 
               may be used to endorse or promote products derived from this software without
               specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
        ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
        ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
        ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
        SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Project-URL: Homepage, https://git.mandelblog.com/mandel-plugins/django-oscar-elasticsearch
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: Django<6,>=4.2
Requires-Dist: django-oscar<5,>=3.2.5
Requires-Dist: purl<2,>=1.6
Requires-Dist: elasticsearch<9,>=8
Requires-Dist: django-oscar-odin<0.3,>=0.2.2
Provides-Extra: test
Requires-Dist: coverage<8,>=7; extra == "test"
Requires-Dist: mock<6,>=5; extra == "test"
Requires-Dist: sorl-thumbnail<13,>=12.10; extra == "test"
Requires-Dist: pytest<9,>=8; extra == "test"
Requires-Dist: pytest-django<5,>=4.8; extra == "test"
Provides-Extra: dev
Requires-Dist: ruff<1,>=0.8; extra == "dev"
Requires-Dist: pylint<4,>=3; extra == "dev"
Requires-Dist: pylint-django<3,>=2.6; extra == "dev"
Dynamic: license-file

# Django Oscar Elasticsearch

## MandelBlog compatibility distribution

`ocyan.compat.django-oscar-elasticsearch` is a private MandelBlog compatibility
distribution based on upstream `django-oscar-elasticsearch` 3.0.0. It preserves
the public Python import namespace (`oscar_elasticsearch`), Django app identity,
and search behaviour. Its packaging changes remove the upstream mandatory
`uwsgidecorators-fallback` dependency, which is not imported by the upstream
runtime package and cannot resolve on supported Python 3.12, and constrain
`django-oscar-odin` to its compatible 0.2.x API line. Upstream source imports
symbols that were renamed in django-oscar-odin 0.3.

Do not install this distribution alongside upstream
`django-oscar-elasticsearch`: both own `oscar_elasticsearch`. MandelBlog
packages must depend on this compatibility distribution explicitly.

## Supported MandelBlog runtime

The certified target is Python 3.10–3.12, Django 4.2–5.2, Django Oscar
3.2.5–4.x, Elasticsearch Python client 8.x, and `django-oscar-odin` 0.2.x.
The compatibility distribution must not be installed alongside upstream
`django-oscar-elasticsearch`, because both provide the same import namespace.

Before enabling indexing, configure `OSCAR_ELASTICSEARCH_SERVER_URLS` with
explicit `http`/`https` service URLs. TLS verification is enabled by default;
use `OSCAR_ELASTICSEARCH_CA_CERTS` for a private CA and, where required,
`OSCAR_ELASTICSEARCH_API_KEY` or the paired username/password settings. The
package never contacts Elasticsearch during import or Django system checks.

The `update_oscar_index` management command is intentionally confirmation
gated: run it with `--confirm` only after reviewing the target configuration.
Signals may enqueue updates after application startup, but no indexing occurs
during package import, app construction, or `manage.py check`.

Validation uses built wheel and sdist artifacts in clean Python 3.12
environments. Editable installs are not part of the supported workflow.

See `NOTICE` for upstream attribution, modification details, and the update
policy. The included BSD-3-Clause licence text is the authoritative licence for
the upstream 3.0.0 source archive.

![PyPI - Version](https://img.shields.io/pypi/v/django-oscar-elasticsearch)

## 🚀 Major Overhaul Update!

The latest version (3.0.0) includes a complete overhaul with significant updates to the codebase, new features, and performance enhancements.

## 📖 About

Django Oscar Elasticsearch is a search app that integrates Elasticsearch with the Django Oscar framework for improved search functionality.

## 🆕 What's New

- **New Elasticsearch Integration**: Enhanced search capabilities using Elasticsearch. We removed wagtail from the dependencies and created our own API.
- **Improved Performance**: Faster and more efficient search operations.
- **Breaking Changes**: Configuration changes may require updates to existing Oscar settings. Also search handlers are removed in djang-oscar==3.2.5

## 📦 Installation

Follow these steps to set up the project:

1. Install the package:
    ```bash
    pip install django-oscar-elasticsearch
    ```
2. Update your `INSTALLED_APPS` in Django settings:
    ```python
    INSTALLED_APPS = [
        ...
        "oscar_elasticsearch.search.apps.OscarElasticSearchConfig",
        "widget_tweaks",
    ]
    ```
3. Configure the necessary settings as outlined in the project documentation.

## 🛠 Configuration

- **`OSCAR_ELASTICSEARCH_HANDLE_STOCKRECORD_CHANGES`**: Enables handling of stock record changes automatically. Default is `True`.
- **`OSCAR_ELASTICSEARCH_MIN_NUM_BUCKETS`**: Minimum number of buckets for search facets. Default is `2`.
- **`OSCAR_ELASTICSEARCH_FILTER_AVAILABLE`**: Filters products based on availability status. Default is `False`.
- **`OSCAR_ELASTICSEARCH_DEFAULT_ITEMS_PER_PAGE`**: Number of items displayed per page. Defaults to `OSCAR_PRODUCTS_PER_PAGE`.
- **`OSCAR_ELASTICSEARCH_ITEMS_PER_PAGE_CHOICES`**: Options for items per page settings. Default is `[DEFAULT_ITEMS_PER_PAGE]`.
- **`OSCAR_ELASTICSEARCH_MONTHS_TO_RUN_ANALYTICS`**: Defines months to run analytics queries. Default is `3`.
- **`OSCAR_ELASTICSEARCH_FACETS`**: Customizable search facets for filtering.
- **`OSCAR_ELASTICSEARCH_SUGGESTION_STATUS_FILTER`**: Status filter for search suggestions, default depends on availability settings.
- **`OSCAR_ELASTICSEARCH_SUGGESTION_FIELD_NAME`**: Field name used for suggestions. Default is `"search_title"`.
- **`OSCAR_ELASTICSEARCH_AUTOCOMPLETE_CONTEXTS`**: Contexts for autocomplete suggestions.
- **`OSCAR_ELASTICSEARCH_AUTOCOMPLETE_SEARCH_FIELDS`**: Fields used in autocomplete search. Default is `["title", "upc"]`.
- **`OSCAR_ELASTICSEARCH_SEARCH_FIELDS`**: Specifies fields used for general search queries.
- **`OSCAR_ELASTICSEARCH_SEARCH_QUERY_TYPE`**: Type of query used in search; default is `"most_fields"`.
- **`OSCAR_ELASTICSEARCH_SEARCH_QUERY_OPERATOR`**: Logical operator for search queries. Default is `"or"`.
- **`OSCAR_ELASTICSEARCH_NUM_SUGGESTIONS`**: Maximum number of suggestions returned. Default is `20`.
- **`OSCAR_ELASTICSEARCH_SERVER_URLS`**: Elasticsearch server URLs. Default is `["http://127.0.0.1:9200"]`.
- **`OSCAR_ELASTICSEARCH_INDEX_PREFIX`**: Prefix used for Elasticsearch indices. Default is `"django-oscar-elasticsearch"`.
- **`OSCAR_ELASTICSEARCH_SORT_BY_CHOICES_SEARCH`**: Sorting options for search results.
- **`OSCAR_ELASTICSEARCH_SORT_BY_MAP_SEARCH`**: Maps sort options to actual query parameters.
- **`OSCAR_ELASTICSEARCH_SORT_BY_CHOICES_CATALOGUE`**: Sorting options specific to the catalog view.
- **`OSCAR_ELASTICSEARCH_SORT_BY_MAP_CATALOGUE`**: Maps catalog sort options to query parameters.
- **`OSCAR_ELASTICSEARCH_DEFAULT_ORDERING`**: Default ordering setting for searches.
- **`OSCAR_ELASTICSEARCH_FACET_BUCKET_SIZE`**: Sets the size of facet buckets. Default is `10`.
- **`OSCAR_ELASTICSEARCH_INDEXING_CHUNK_SIZE`**: Defines chunk size for batch indexing operations. Default is `400`.
- **`OSCAR_ELASTICSEARCH_PRIORITIZE_AVAILABLE_PRODUCTS`**: Prioritizes available products in search results. Default is `True`.


## 📜 Usage

Django Oscar Elasticsearch is designed primarily to index products and categories from Django Oscar, but it can also index any Django model or external data types, such as CSV or Excel files.

### Indexing Django Models
You can configure custom search handlers to index any Django model. Define a search document, map the fields you want to index, and create a corresponding search handler.

Create the index definition
```python
from django.contrib.auth import get_user_model

from oscar.core.loading import get_class, get_model

get_oscar_index_settings = get_class(
    "search.indexing.settings", "get_oscar_index_settings"
)

OSCAR_INDEX_SETTINGS = get_oscar_index_settings()

BaseElasticSearchApi = get_class("search.api.search", "BaseElasticSearchApi")
ESModelIndexer = get_class("search.indexing.indexer", "ESModelIndexer")


class UserElasticsearchIndex(BaseElasticSearchApi, ESModelIndexer):
    INDEX_NAME = "users"
    INDEX_MAPPING = {
        "properties": {
            "id": {"type": "integer", "store": True},
            "full_name": {"type": "text"},
            "is_active": {"type": "boolean"}
        }
    }
    INDEX_SETTINGS = OSCAR_INDEX_SETTINGS
    Model = get_user_model()

    def make_documents(self, objects):
        for user in objects:
            yield {"_id": user.id, "_source": {"id": user.id, "full_name": user.get_full_name(), "is_active": user.is_active}}
```

Indexing users into elasticsearch, this can be done in a management command for example
```python
from django.contrib.auth import get_user_model
from oscar_elasticsearch.search import settings

from myprojects.usersearch import UserElasticsearchIndex

User = get_user_model()


with UserElasticsearchIndex().reindex() as index:
    for chunk in chunked(users, settings.INDEXING_CHUNK_SIZE):
        index.reindex_objects(chunk)
```

Searching for users on full_name
```python
from myprojects.usersearch import UserElasticsearchIndex

# non paginated, returns a queryset of selected model
users = UserElasticsearchIndex().search(
    from_=0,
    to=10,
    query_string="henk",
    search_fields=["full_name^1.5"],
    filters={"term": {"is_active_": True}}, # only active users
)

# paginated, returns a paginator object that extends from the django paginator
paginator = UserElasticsearchIndex().paginated_search(
    from_=0,
    to=10,
    query_string="henk",
    search_fields=["full_name^1.5"],
    filters={"term": {"is_active_": True}}, # only active users
)
```

## 🤝 Contributing

Contributions are welcome! Please submit issues and pull requests to the repository.

## 📄 License

Oscar is released under the permissive [New BSD license](https://github.com/django-oscar/django-oscar-elasticsearch/blob/master/LICENSE) ([see summary](https://tldrlegal.com/license/bsd-3-clause-license-(revised))).

## 📫 Contact

For questions or support, please contact the maintainers via GitHub issues.
