Metadata-Version: 2.4
Name: wagtail-instance-selector
Version: 3.1.0
Summary: A widget for Wagtail's admin that allows you to create and select related items
Author-email: The Interaction Consortium <studio@interaction.net.au>
Maintainer-email: The Interaction Consortium <studio@interaction.net.au>
License: MIT License
        
        Copyright (c) 2019 The Interaction Consortium
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: homepage, https://github.com/ixc/wagtail-instance-selector
Project-URL: issues, https://github.com/ixc/wagtail-instance-selector/issues
Project-URL: repository, https://github.com/ixc/wagtail-instance-selector.git
Project-URL: changelog, https://github.com/ixc/wagtail-instance-selector/blob/main/CHANGELOG.md
Keywords: wagtail,instance,selector
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Wagtail
Classifier: Framework :: Wagtail :: 6
Classifier: Framework :: Wagtail :: 7
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: wagtail>=6.3
Requires-Dist: wagtail-modeladmin
Provides-Extra: testing
Requires-Dist: django_webtest; extra == "testing"
Provides-Extra: dev
Requires-Dist: django>=4.2; extra == "dev"
Requires-Dist: ruff==0.12.12; extra == "dev"
Requires-Dist: ipdb<1.0,>=0.13; extra == "dev"
Dynamic: license-file

# wagtail-instance-selector

A widget for Wagtail's admin that allows you to create and select related items.

- [Features and screenshots](#features-and-screenshots)
- [Installation](#installation)
- [Documentation](#documentation)
  - [Using the widget as a field panel](#using-the-widget-as-a-field-panel)
  - [Using the widget in a stream field](#using-the-widget-in-a-stream-field)
  - [Customizing the widget's display and behaviour](#customizing-the-widgets-display-and-behaviour)
- [Rationale & Credits](#rationale--credits)
- [Development notes](#development-notes)


## Features and screenshots

### Customizable widget display

By default, widgets appear similar to other Wagtail elements, but they can be customised to include images
and other items.

![](./images/fields.png)


### Item selection reuses the admin's list views to ensure consistent UIs with filtering.

![](./images/list_view.png)


### Inline creation

Items can be created within the selection widget.

![](./images/creation.png)

After creation, items can be selected from the success message or from the list view.

![](./images/post_creation.png)


## Installation

```
pip install wagtail-instance-selector
```

and add `'instance_selector'` and `'wagtail_modeladmin'` to `INSTALLED_APPS`.

If you're using Django 3+, you will need to change Django's iframe security flag in your settings:

```python
X_FRAME_OPTIONS = 'SAMEORIGIN'
```


## Documentation


### Using the widget as a field panel

```python
from django.db import models
from instance_selector.edit_handlers import InstanceSelectorPanel


class Shop(models.Model):
    pass


class Product(models.Model):
    shop = models.ForeignKey(Shop, on_delete=models.CASCADE)

    panels = [InstanceSelectorPanel("shop")]
```


#### Using the widget in a stream field

```python
from django.db import models
from wagtail.admin.panels import FieldPanel
from wagtail.fields import StreamField
from instance_selector.blocks import InstanceSelectorBlock


class Product(models.Model):
    pass


class Service(models.Model):
    pass


class Shop(models.Model):
    content = StreamField([
        ("products", InstanceSelectorBlock(target_model="test_app.Product")),
        ("services", InstanceSelectorBlock(target_model="test_app.Service")),
    ], use_json_field=True)

    panels = [FieldPanel("content")]
```

To create reusable blocks, you can subclass `InstanceSelectorBlock`.

```python
from instance_selector.blocks import InstanceSelectorBlock


class ProductBlock(InstanceSelectorBlock):
    def __init__(self, *args, **kwargs):
        target_model = kwargs.pop("target_model", "my_app.Product")
        super().__init__(target_model=target_model, **kwargs)

    class Meta:
        icon = "image"

# ...

StreamField([
    ("products", ProductBlock()),
])
```


### Customizing the widget's display and behaviour

```python
from wagtail_modeladmin.options import ModelAdmin, modeladmin_register
from instance_selector.registry import registry
from instance_selector.selectors import ModelAdminInstanceSelector
from .models import MyModel


@modeladmin_register
class MyModelAdmin(ModelAdmin):
    model = MyModel


class MyModelInstanceSelector(ModelAdminInstanceSelector):
    model_admin = MyModelAdmin()

    def get_instance_display_title(self, instance):
        if instance:
            return "some title"

    def get_instance_display_image_url(self, instance):
        if instance:
            return "/url/to/some/image.jpg"

    def get_instance_display_image_styles(self, instance):
        # The `style` properties set on the <img> element, primarily of use
        # to work within style+layout patterns
        if instance:
            return {
                'max-width': '165px',
                # ...
            }

    def get_instance_display_markup(self, instance):
        # Overriding this method allows you to completely control how the
        # widget will display the relation to this specific model
        return "<div> ... </div>"

    def get_instance_display_template(self):
        # The template used by `get_instance_display_markup`
        return "instance_selector/instance_selector_widget_display.html"

    def get_instance_selector_url(self):
        # The url that the widget will render within a modal. By default, this
        # is the ModelAdmin"s list view
        return "/url/to/some/view/"

    def get_instance_edit_url(self, instance):
        # The url that the user can edit the instance on. By default, this is
        # the ModelAdmin"s edit view
        if instance:
            return "/url/to/some/view/"


registry.register_instance_selector(MyModel, MyModelInstanceSelector())
```

Note that the `ModelAdminInstanceSelector` is designed for the common case. If your needs
are more specific, you may find some use in `instance_selector.selectors.BaseInstanceSelector`.


## Rationale & Credits

Largely, this is a rewrite of [neon-jungle/wagtailmodelchooser](https://github.com/neon-jungle/wagtailmodelchooser)
that focuses on reusing the functionality in the ModelAdmins. We had started a large build using wagtailmodelchooser
heavily, but quickly ran into UI problems when users needed to filter the objects or create them inline. After
[neon-jungle/wagtailmodelchooser#11](https://github.com/neon-jungle/wagtailmodelchooser/issues/11) received little
response, the decision was made to piece together parts from the ecosystem and replicate the flexibility of
django's `raw_id_fields`, while preserving the polish in Wagtail's UI.

Much of this library was built atop of the work of others, specifically:
- https://github.com/neon-jungle/wagtailmodelchooser
- https://github.com/springload/wagtailmodelchoosers
- https://github.com/Naeka/wagtailmodelchooser


## Development notes


### Run tests

```
pip install -r requirements.txt
python runtests.py
```


### Linting and formatting

```bash
pip install -r requirements.txt
ruff check
ruff format
```
