Metadata-Version: 2.4
Name: django-searchfield
Version: 0.1.0
Summary: Django field that combines multiple fields into a concatenated value with collision handling
Author-email: Octolo <dev@octolo.tech>
License-Expression: MIT
Project-URL: Homepage, https://github.com/octolo/django-searchfield
Project-URL: Repository, https://github.com/octolo/django-searchfield
Project-URL: Documentation, https://github.com/octolo/django-searchfield#readme
Project-URL: Issues, https://github.com/octolo/django-searchfield/issues
Keywords: django,django-field,unique-identifier,composite-field,search-field,concatenate-fields,django-orm,python
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Framework :: Django
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.0
Classifier: Framework :: Django :: 4.1
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Django>=3.2
Provides-Extra: dev
Requires-Dist: pytest>=8.3; extra == "dev"
Requires-Dist: pytest-django>=4.5; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: django-stubs>=5.0.0; extra == "dev"
Dynamic: license-file

# django-searchfield

Django field that concatenates multiple fields into a search-indexed string (mighty-style).

## Purpose

Create a full-text search field by combining multiple model fields. Values are concatenated with `_` by default for simple `startswith` / `icontains` queries.

## Installation

```bash
pip install django-searchfield
```

## Quick Start

### Using SearchField directly

```python
from django.db import models
from searchfield import SearchField

class Product(models.Model):
    name = models.CharField(max_length=100)
    code = models.IntegerField()
    created_date = models.DateField()

    search = SearchField(source_fields=["name", "code", "created_date"])
```

### Using the decorator

```python
from django.db import models
from searchfield import add_searchfield

@add_searchfield(search=["title", "category"])
class Article(models.Model):
    title = models.CharField(max_length=200)
    category = models.CharField(max_length=50)
    content = models.TextField()
```

### Path resolution (relations, JSON)

```python
class Creditor(models.Model):
    contact = models.ForeignKey(Contact, ...)
    contact_data = models.JSONField()  # {"firstname": "...", "lastname": "..."}

    search = SearchField(source_fields=[
        "name",
        "contact.lastname",       # relation
        "contact_data.firstname", # JSON keys
    ])
```

## Features

- **Automatic generation**: Values are generated automatically before saving
- **Path resolution**: Source paths support dotted notation (`name`, `contact.lastname`, `contact_data.firstname` for JSON)
- **Search indexing**: Normalized values (NFKD, lowercase) concatenated with `_` for `startswith`/`icontains`
- **Type formatting**: Automatically formats dates, numbers, booleans
- **Read-only**: Field is editable=False
- **db_index=True**: Indexed for search performance
- **unique=False**: Not unique by default (allows homonyms); pass unique=True to enforce

## Field Properties

- `editable=False`: Read-only
- `blank=True`, `null=True`: Optional (empty if all source fields are empty)
- `db_index=True`: Indexed for search queries
- `unique=False`: Homonyms allowed by default

## Development

```bash
./service.py dev install-dev
./service.py dev test
```

## License

MIT
