django-tomselect


Namedjango-tomselect JSON
Version 0.4.4 PyPI version JSON
download
home_page
SummaryDjango autocomplete widgets and views using Tom Select
upload_time2023-10-10 01:53:25
maintainer
docs_urlNone
author
requires_python>=3.8
license
keywords
VCS
bugtrack_url
requirements Django coverage tox pytest pytest-django pytest-xdist pytest-cov pytest-playwright playwright black ruff build twine
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# Tom Select for Django

Django autocomplete widgets and views using [Tom Select](https://tom-select.js.org/).

This package provides a Django autocomplete widget and view that can be used
together to provide a user interface for selecting a model instance from a
database table.

The package is adapted from the fantastic work of 
[Philip Becker](https://pypi.org/user/actionb/) in 
[mizdb-tomselect](https://www.pypi.org/project/mizdb-tomselect/), with the goal 
of a more generalized solution for Django autocompletion.

<!-- TOC -->
* [Tom Select for Django](#tom-select-for-django)
  * [Installation](#installation)
  * [Usage](#usage)
  * [Widgets](#widgets)
    * [TomSelectWidget](#tomselectwidget)
    * [TomSelectTabularWidget](#tomselecttabularwidget)
      * [Adding more columns](#adding-more-columns-)
  * [Settings](#settings)
    * [TOMSELECT_BOOTSTRAP_VERSION](#tomselectbootstrapversion)
  * [Function & Features](#function--features)
    * [Modifying the initial QuerySet](#modifying-the-initial-queryset)
    * [Searching](#searching)
    * [Option creation](#option-creation)
      * [AJAX request](#ajax-request)
    * [List View link](#list-view-link)
    * [Chained Dropdown Filtering](#chained-dropdown-filtering)
  * [Manually Initializing Tom Select Fields](#manually-initializing-tom-select-fields)
  * [Development & Demo](#development--demo)
<!-- TOC -->

----

## Installation

Install:

```bash
pip install -U django-tomselect
```

## Usage

Add to installed apps:

```python
INSTALLED_APPS = [
    # ...
    "django_tomselect"
]
```

Configure an endpoint for autocomplete requests:

```python
# urls.py
from django.urls import path

from django_tomselect.views import AutocompleteView

urlpatterns = [
    # ...
    path("autocomplete/", AutocompleteView.as_view(), name="my_autocomplete_view")
]
```

Use the widgets in a form.

```python
from django import forms

from django_tomselect.widgets import TomSelectWidget, TomSelectTabularWidget
from .models import City, Person


class MyForm(forms.Form):
    city = forms.ModelChoiceField(
        City.objects.all(),
        widget=TomSelectWidget(City, url="my_autocomplete_view"),
    )

    # Display results in a table, with additional columns for fields
    # "first_name" and "last_name":
    person = forms.ModelChoiceField(
        Person.objects.all(),
        widget=TomSelectTabularWidget(
            url="my_autocomplete_view",
            search_lookups=[
                "full_name__icontains",
            ],
            # for extra columns pass a mapping of {"model_field": "Column Header Label"}
            extra_columns={"first_name": "First Name", "last_name": "Last Name"},
            # The column header label for the labelField column
            label_field_label="Full Name",
        ),
    )

``` 

NOTE: Make sure to include [bootstrap](https://getbootstrap.com/docs/5.2/getting-started/download/) somewhere. For example in the template:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Tom Select Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    {{ form.media }}
</head>
<body>
<div class="container">
    <form>
        {% csrf_token %}
        {{ form.as_div }}
        <button type="submit" class="btn btn-success">Save</button>
    </form>
</div>
</body>
</html>
```

----

## Widgets

The widgets pass attributes necessary to make autocomplete requests to the
HTML element via the dataset property. The Tom Select element is then initialized
from the attributes in the dataset property.

### TomSelectWidget & TomSelectMultipleWidget

Base autocomplete widgets for `ModelChoiceField` and `ModelMultipleChoiceField`. The arguments of TomSelectWidget & TomSelectMultipleWidget are:

| Argument          | Default value                                                           | Description                                                                        |
|-------------------|-------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| model             | **required**                                                            | the model class that provides the choices                                          |
| url               | `"autocomplete"`                                                        | URL pattern name of the autocomplete view                                          |
| value_field       | `f"{model._meta.pk.name}"`                                              | model field that provides the value of an option                                   |
| label_field       | `getattr(model, "name_field", "name")`                                  | model field that provides the label of an option                                   |
| search_lookups    | `[f"{self.value_field}__icontains", f"{self.label_field}__icontains"]`  | the list of lookups to use when filtering the results                              |
| create_field      | ""                                                                      | model field to create new objects with ([see below](#ajax-request))                ||
| listview_url      | ""                                                                      | URL name of the list view for this model ([see below](#list-view-link))            |
| add_url           | ""                                                                      | URL name of the add view for this model([see below](#option-creation))             |
| edit_url           | ""                                                                      | URL name of the edit view for each instance of this model([see below](#option-edits))             |
| filter_by         | ()                                                                      | a 2-tuple defining an additional filter ([see below](#chained-dropdown-filtering)) |
| bootstrap_version | 5                                                                       | the bootstrap version to use, either `4` or `5`                                    |

### TomSelectTabularWidget & TomSelectTabularMultipleWidget

These widgets displays the results in tabular form. A table header will be added
to the dropdown. By default, the table contains two columns: one column for the choice 
value (commonly the "ID" of the option) and one column for the choice label (the 
human-readable part of the choice).

![Tabular select preview](https://raw.githubusercontent.com/jacklinke/django-tomselect/main/assets/tomselect_tabular.png "Tabular select preview")

TomSelectTabularWidget & TomSelectTabularMultipleWidget have the following additional arguments:

| Argument          | Default value                   | Description                                  |
|-------------------|---------------------------------|----------------------------------------------|
| extra_columns     |                                 | a mapping for additional columns             |
| value_field_label | `f"{value_field.title()}"`      | table header for the value column            |
| label_field_label | `f"{model._meta.verbose_name}"` | table header for the label column            |
| label_field_label | `f"{model._meta.verbose_name}"` | table header for the label column            |
| show_value_field  | `False`                         | show the value field column (typically `id`) |

#### Adding more columns to the tabular widgets

To add more columns, pass a dictionary mapping field names to column labels as
`extra_columns` to the widget's arguments.

```python
from django import forms
from django_tomselect.widgets import TomSelectTabularWidget
from .models import Person


class MyForm(forms.Form):
    person = forms.ModelChoiceField(
        Person.objects.all(),
        widget=TomSelectTabularWidget(
            url="my_autocomplete_view",
            # for extra columns pass a mapping of {"model_field": "Column Header Label"}
            extra_columns={"first_name": "First Name", "last_name": "Last Name"},
        ),
    )

```

The column label is the header label for a given column in the table.  

The attribute name tells Tom Select what value to look up on a result for the column.

**Important**: that means that the result visible to Tom Select must have an attribute
or property with that name or the column will remain empty. 
The results for Tom Select are created by the view calling `values()` on the 
result queryset, so you must make sure that the attribute name is available
on the view's root queryset as either a model field or as an annotation.

----

## Settings

| Setting | Default value | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
|---------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| TOMSELECT_BOOTSTRAP_VERSION | `5` | The bootstrap version to use. Either `4` or `5`. Defaults to `5`. This sets the project-wide default for the `bootstrap_version` argument of the widgets. <p>You can overwrite the default for a specific widget by passing the `bootstrap_version` argument to the widget. This sets the project-wide default for the `bootstrap_version` argument of the widgets. You can overwrite the default for a specific widget by passing the `bootstrap_version` argument to the widget.</p>                                                                           |
| TOMSELECT_PROXY_REQUEST | `"django_tomselect.utils.DefaultProxyRequest"` | Either a direct reference to a DefaultProxyRequest subclass or the path to the DefaultProxyRequest subclass to use. This class is used to obtain the model details for the autocomplete. <p>In order to simplify the process of creating a custom autocomplete view, django-tomselect provides a `DefaultProxyRequest` class that can be used to obtain the model details from the queryset and the request. This class is used by the widget to obtain the model details for the autocomplete. In most cases, you will not need to use this class directly.</p> |

----

## Function & Features

### Modifying the initial QuerySet

If you want to modify all autocomplete queries for a subclassed AutocompleteView, you can use `super()` with the `get_queryset()` method.

```python
from django_tomselect.views import AutocompleteView


class MyAutocompleteView(AutocompleteView):
    def get_queryset(self):
        """Toy example of filtering all queries in this view to id values less than 10"""
        queryset = super().get_queryset()
        queryset.filter(id__lt=10)
        return queryset
```

### Searching

The AutocompleteView filters the result QuerySet against the `search_lookups`
passed to the widget. The default value for the lookup is `name__icontains`.
Overwrite the `AutocompleteView.search` method to modify the search process.

```python
from django_tomselect.views import AutocompleteView


class MyAutocompleteView(AutocompleteView):
    def search(self, queryset, q):
        # Filter using your own queryset method:
        return queryset.search(q)
```

### Option creation

To enable option creation in the dropdown, pass the URL pattern name of the 
add page of the given model to the widget. This will add an 'Add' button to the
bottom of the dropdown.

```python
# urls.py
from django.urls import path
from django_tomselect.views import AutocompleteView
from django_tomselect.widgets import TomSelectWidget
from .models import City
from .views import CityAddView

urlpatterns = [
    # ...
    path("autocomplete/", AutocompleteView.as_view(), name="my_autocomplete_view"),
    path("city/add/", CityAddView.as_view(), name="city_add"),
]

# forms.py
widget = TomSelectWidget(City, url="my_autocomplete_view", add_url="city_add")
```

Clicking on that button sends the user to the add page of the model.

#### AJAX request

If `create_field` was also passed to the widget, clicking on the button will
create a new object using an AJAX POST request to the autocomplete URL. The
autocomplete view will use the search term that the user put in on the
`create_field` to create the object:

```python
class AutocompleteView:
    
    def create_object(self, data):
        """Create a new object with the given data."""
        return self.model.objects.create(**{self.create_field: data[self.create_field]})
```

Override the view's `create_object` method to change the creation process.

### List View link

The dropdown will include a link to the list view of the given model if you
pass in the URL pattern name of the list view.

```python
# urls.py
from django.urls import path
from django_tomselect.views import AutocompleteView
from django_tomselect.widgets import TomSelectWidget
from .models import City
from .views import CityListView

urlpatterns = [
    # ...
    path("autocomplete/", AutocompleteView.as_view(), name="my_autocomplete_view"),
    path("city/list/", CityListView.as_view(), name="city_listview"),
]

# forms.py
widget = TomSelectWidget(City, url="my_autocomplete_view", listview_url="city_listview")
```

### Chained Dropdown Filtering

Use the `filter_by` argument to restrict the available options of one 
TomSelectWidget to the value selected in another form field. The parameter must 
be a 2-tuple:  `(name_of_the_other_form_field, django_field_lookup)`

```python
# models.py
from django import forms
from django.db import models
from django_tomselect.widgets import TomSelectWidget


class Person(models.Model):
    name = models.CharField(max_length=50)
    city = models.ForeignKey("City", on_delete=models.SET_NULL, blank=True, null=True)


class City(models.Model):
    name = models.CharField(max_length=50)
    is_capitol = models.BooleanField(default=False)


# forms.py
class PersonsFromCapitolsForm(forms.Form):
    capitol = forms.ModelChoiceField(queryset=City.objects.filter(is_capitol=True))
    person = forms.ModelChoiceField(
        queryset=Person.objects.all(),
        widget=TomSelectWidget(Person, filter_by=("capitol", "city_id")),
    )
```

This will result in the Person result queryset to be filtered against 
`city_id` for the currently selected `capitol` formfield value.  
NOTE: When using `filter_by`, the declaring element now **requires** that the 
other field provides a value, since its choices are dependent on the other 
field. If the other field does not have a value, the search will not return any 
results.

## Advanced Topics

### Manually Initializing Tom Select Fields

If a form is added dynamically after the page loads (e.g.: with htmx), the new form 
fields will not be initialized as django-tomselect fields. In order to manually 
initialize them, dispatch a `triggerTomSelect` event, providing the id of the 
form field as a value in `detail` as follows.

```javascript
<script>
  window.dispatchEvent(new CustomEvent('triggerTomSelect', {
    detail: {
        elemID: 'id_tomselect_tabular'
    }
  }));
</script>
````

---

## Development & Demo

```bash
python3 -m venv venv
source venv/bin/activate
make init
```

Then see the demo for a preview: `python demo/manage.py runserver`

Run tests with `make test` or `make tox`. To install required browsers for playwright: `playwright install`.
See the makefile for other commands.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "django-tomselect",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "",
    "author": "",
    "author_email": "Jack Linke <jacklinke@gmail.com>, Philip Becker <yummytea1@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/94/2f/f45a4ff04eb457812ba77022fdf1a4b4578e65b43e69c29b1c9f346e8c99/django-tomselect-0.4.4.tar.gz",
    "platform": null,
    "description": "\n# Tom Select for Django\n\nDjango autocomplete widgets and views using [Tom Select](https://tom-select.js.org/).\n\nThis package provides a Django autocomplete widget and view that can be used\ntogether to provide a user interface for selecting a model instance from a\ndatabase table.\n\nThe package is adapted from the fantastic work of \n[Philip Becker](https://pypi.org/user/actionb/) in \n[mizdb-tomselect](https://www.pypi.org/project/mizdb-tomselect/), with the goal \nof a more generalized solution for Django autocompletion.\n\n<!-- TOC -->\n* [Tom Select for Django](#tom-select-for-django)\n  * [Installation](#installation)\n  * [Usage](#usage)\n  * [Widgets](#widgets)\n    * [TomSelectWidget](#tomselectwidget)\n    * [TomSelectTabularWidget](#tomselecttabularwidget)\n      * [Adding more columns](#adding-more-columns-)\n  * [Settings](#settings)\n    * [TOMSELECT_BOOTSTRAP_VERSION](#tomselectbootstrapversion)\n  * [Function & Features](#function--features)\n    * [Modifying the initial QuerySet](#modifying-the-initial-queryset)\n    * [Searching](#searching)\n    * [Option creation](#option-creation)\n      * [AJAX request](#ajax-request)\n    * [List View link](#list-view-link)\n    * [Chained Dropdown Filtering](#chained-dropdown-filtering)\n  * [Manually Initializing Tom Select Fields](#manually-initializing-tom-select-fields)\n  * [Development & Demo](#development--demo)\n<!-- TOC -->\n\n----\n\n## Installation\n\nInstall:\n\n```bash\npip install -U django-tomselect\n```\n\n## Usage\n\nAdd to installed apps:\n\n```python\nINSTALLED_APPS = [\n    # ...\n    \"django_tomselect\"\n]\n```\n\nConfigure an endpoint for autocomplete requests:\n\n```python\n# urls.py\nfrom django.urls import path\n\nfrom django_tomselect.views import AutocompleteView\n\nurlpatterns = [\n    # ...\n    path(\"autocomplete/\", AutocompleteView.as_view(), name=\"my_autocomplete_view\")\n]\n```\n\nUse the widgets in a form.\n\n```python\nfrom django import forms\n\nfrom django_tomselect.widgets import TomSelectWidget, TomSelectTabularWidget\nfrom .models import City, Person\n\n\nclass MyForm(forms.Form):\n    city = forms.ModelChoiceField(\n        City.objects.all(),\n        widget=TomSelectWidget(City, url=\"my_autocomplete_view\"),\n    )\n\n    # Display results in a table, with additional columns for fields\n    # \"first_name\" and \"last_name\":\n    person = forms.ModelChoiceField(\n        Person.objects.all(),\n        widget=TomSelectTabularWidget(\n            url=\"my_autocomplete_view\",\n            search_lookups=[\n                \"full_name__icontains\",\n            ],\n            # for extra columns pass a mapping of {\"model_field\": \"Column Header Label\"}\n            extra_columns={\"first_name\": \"First Name\", \"last_name\": \"Last Name\"},\n            # The column header label for the labelField column\n            label_field_label=\"Full Name\",\n        ),\n    )\n\n``` \n\nNOTE: Make sure to include [bootstrap](https://getbootstrap.com/docs/5.2/getting-started/download/) somewhere. For example in the template:\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Django Tom Select Demo</title>\n    <script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4\" crossorigin=\"anonymous\"></script>\n    <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65\" crossorigin=\"anonymous\">\n    {{ form.media }}\n</head>\n<body>\n<div class=\"container\">\n    <form>\n        {% csrf_token %}\n        {{ form.as_div }}\n        <button type=\"submit\" class=\"btn btn-success\">Save</button>\n    </form>\n</div>\n</body>\n</html>\n```\n\n----\n\n## Widgets\n\nThe widgets pass attributes necessary to make autocomplete requests to the\nHTML element via the dataset property. The Tom Select element is then initialized\nfrom the attributes in the dataset property.\n\n### TomSelectWidget & TomSelectMultipleWidget\n\nBase autocomplete widgets for `ModelChoiceField` and `ModelMultipleChoiceField`. The arguments of TomSelectWidget & TomSelectMultipleWidget are:\n\n| Argument          | Default value                                                           | Description                                                                        |\n|-------------------|-------------------------------------------------------------------------|------------------------------------------------------------------------------------|\n| model             | **required**                                                            | the model class that provides the choices                                          |\n| url               | `\"autocomplete\"`                                                        | URL pattern name of the autocomplete view                                          |\n| value_field       | `f\"{model._meta.pk.name}\"`                                              | model field that provides the value of an option                                   |\n| label_field       | `getattr(model, \"name_field\", \"name\")`                                  | model field that provides the label of an option                                   |\n| search_lookups    | `[f\"{self.value_field}__icontains\", f\"{self.label_field}__icontains\"]`  | the list of lookups to use when filtering the results                              |\n| create_field      | \"\"                                                                      | model field to create new objects with ([see below](#ajax-request))                ||\n| listview_url      | \"\"                                                                      | URL name of the list view for this model ([see below](#list-view-link))            |\n| add_url           | \"\"                                                                      | URL name of the add view for this model([see below](#option-creation))             |\n| edit_url           | \"\"                                                                      | URL name of the edit view for each instance of this model([see below](#option-edits))             |\n| filter_by         | ()                                                                      | a 2-tuple defining an additional filter ([see below](#chained-dropdown-filtering)) |\n| bootstrap_version | 5                                                                       | the bootstrap version to use, either `4` or `5`                                    |\n\n### TomSelectTabularWidget & TomSelectTabularMultipleWidget\n\nThese widgets displays the results in tabular form. A table header will be added\nto the dropdown. By default, the table contains two columns: one column for the choice \nvalue (commonly the \"ID\" of the option) and one column for the choice label (the \nhuman-readable part of the choice).\n\n![Tabular select preview](https://raw.githubusercontent.com/jacklinke/django-tomselect/main/assets/tomselect_tabular.png \"Tabular select preview\")\n\nTomSelectTabularWidget & TomSelectTabularMultipleWidget have the following additional arguments:\n\n| Argument          | Default value                   | Description                                  |\n|-------------------|---------------------------------|----------------------------------------------|\n| extra_columns     |                                 | a mapping for additional columns             |\n| value_field_label | `f\"{value_field.title()}\"`      | table header for the value column            |\n| label_field_label | `f\"{model._meta.verbose_name}\"` | table header for the label column            |\n| label_field_label | `f\"{model._meta.verbose_name}\"` | table header for the label column            |\n| show_value_field  | `False`                         | show the value field column (typically `id`) |\n\n#### Adding more columns to the tabular widgets\n\nTo add more columns, pass a dictionary mapping field names to column labels as\n`extra_columns` to the widget's arguments.\n\n```python\nfrom django import forms\nfrom django_tomselect.widgets import TomSelectTabularWidget\nfrom .models import Person\n\n\nclass MyForm(forms.Form):\n    person = forms.ModelChoiceField(\n        Person.objects.all(),\n        widget=TomSelectTabularWidget(\n            url=\"my_autocomplete_view\",\n            # for extra columns pass a mapping of {\"model_field\": \"Column Header Label\"}\n            extra_columns={\"first_name\": \"First Name\", \"last_name\": \"Last Name\"},\n        ),\n    )\n\n```\n\nThe column label is the header label for a given column in the table.  \n\nThe attribute name tells Tom Select what value to look up on a result for the column.\n\n**Important**: that means that the result visible to Tom Select must have an attribute\nor property with that name or the column will remain empty. \nThe results for Tom Select are created by the view calling `values()` on the \nresult queryset, so you must make sure that the attribute name is available\non the view's root queryset as either a model field or as an annotation.\n\n----\n\n## Settings\n\n| Setting | Default value | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n|---------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| TOMSELECT_BOOTSTRAP_VERSION | `5` | The bootstrap version to use. Either `4` or `5`. Defaults to `5`. This sets the project-wide default for the `bootstrap_version` argument of the widgets. <p>You can overwrite the default for a specific widget by passing the `bootstrap_version` argument to the widget. This sets the project-wide default for the `bootstrap_version` argument of the widgets. You can overwrite the default for a specific widget by passing the `bootstrap_version` argument to the widget.</p>                                                                           |\n| TOMSELECT_PROXY_REQUEST | `\"django_tomselect.utils.DefaultProxyRequest\"` | Either a direct reference to a DefaultProxyRequest subclass or the path to the DefaultProxyRequest subclass to use. This class is used to obtain the model details for the autocomplete. <p>In order to simplify the process of creating a custom autocomplete view, django-tomselect provides a `DefaultProxyRequest` class that can be used to obtain the model details from the queryset and the request. This class is used by the widget to obtain the model details for the autocomplete. In most cases, you will not need to use this class directly.</p> |\n\n----\n\n## Function & Features\n\n### Modifying the initial QuerySet\n\nIf you want to modify all autocomplete queries for a subclassed AutocompleteView, you can use `super()` with the `get_queryset()` method.\n\n```python\nfrom django_tomselect.views import AutocompleteView\n\n\nclass MyAutocompleteView(AutocompleteView):\n    def get_queryset(self):\n        \"\"\"Toy example of filtering all queries in this view to id values less than 10\"\"\"\n        queryset = super().get_queryset()\n        queryset.filter(id__lt=10)\n        return queryset\n```\n\n### Searching\n\nThe AutocompleteView filters the result QuerySet against the `search_lookups`\npassed to the widget. The default value for the lookup is `name__icontains`.\nOverwrite the `AutocompleteView.search` method to modify the search process.\n\n```python\nfrom django_tomselect.views import AutocompleteView\n\n\nclass MyAutocompleteView(AutocompleteView):\n    def search(self, queryset, q):\n        # Filter using your own queryset method:\n        return queryset.search(q)\n```\n\n### Option creation\n\nTo enable option creation in the dropdown, pass the URL pattern name of the \nadd page of the given model to the widget. This will add an 'Add' button to the\nbottom of the dropdown.\n\n```python\n# urls.py\nfrom django.urls import path\nfrom django_tomselect.views import AutocompleteView\nfrom django_tomselect.widgets import TomSelectWidget\nfrom .models import City\nfrom .views import CityAddView\n\nurlpatterns = [\n    # ...\n    path(\"autocomplete/\", AutocompleteView.as_view(), name=\"my_autocomplete_view\"),\n    path(\"city/add/\", CityAddView.as_view(), name=\"city_add\"),\n]\n\n# forms.py\nwidget = TomSelectWidget(City, url=\"my_autocomplete_view\", add_url=\"city_add\")\n```\n\nClicking on that button sends the user to the add page of the model.\n\n#### AJAX request\n\nIf `create_field` was also passed to the widget, clicking on the button will\ncreate a new object using an AJAX POST request to the autocomplete URL. The\nautocomplete view will use the search term that the user put in on the\n`create_field` to create the object:\n\n```python\nclass AutocompleteView:\n    \n    def create_object(self, data):\n        \"\"\"Create a new object with the given data.\"\"\"\n        return self.model.objects.create(**{self.create_field: data[self.create_field]})\n```\n\nOverride the view's `create_object` method to change the creation process.\n\n### List View link\n\nThe dropdown will include a link to the list view of the given model if you\npass in the URL pattern name of the list view.\n\n```python\n# urls.py\nfrom django.urls import path\nfrom django_tomselect.views import AutocompleteView\nfrom django_tomselect.widgets import TomSelectWidget\nfrom .models import City\nfrom .views import CityListView\n\nurlpatterns = [\n    # ...\n    path(\"autocomplete/\", AutocompleteView.as_view(), name=\"my_autocomplete_view\"),\n    path(\"city/list/\", CityListView.as_view(), name=\"city_listview\"),\n]\n\n# forms.py\nwidget = TomSelectWidget(City, url=\"my_autocomplete_view\", listview_url=\"city_listview\")\n```\n\n### Chained Dropdown Filtering\n\nUse the `filter_by` argument to restrict the available options of one \nTomSelectWidget to the value selected in another form field. The parameter must \nbe a 2-tuple:  `(name_of_the_other_form_field, django_field_lookup)`\n\n```python\n# models.py\nfrom django import forms\nfrom django.db import models\nfrom django_tomselect.widgets import TomSelectWidget\n\n\nclass Person(models.Model):\n    name = models.CharField(max_length=50)\n    city = models.ForeignKey(\"City\", on_delete=models.SET_NULL, blank=True, null=True)\n\n\nclass City(models.Model):\n    name = models.CharField(max_length=50)\n    is_capitol = models.BooleanField(default=False)\n\n\n# forms.py\nclass PersonsFromCapitolsForm(forms.Form):\n    capitol = forms.ModelChoiceField(queryset=City.objects.filter(is_capitol=True))\n    person = forms.ModelChoiceField(\n        queryset=Person.objects.all(),\n        widget=TomSelectWidget(Person, filter_by=(\"capitol\", \"city_id\")),\n    )\n```\n\nThis will result in the Person result queryset to be filtered against \n`city_id` for the currently selected `capitol` formfield value.  \nNOTE: When using `filter_by`, the declaring element now **requires** that the \nother field provides a value, since its choices are dependent on the other \nfield. If the other field does not have a value, the search will not return any \nresults.\n\n## Advanced Topics\n\n### Manually Initializing Tom Select Fields\n\nIf a form is added dynamically after the page loads (e.g.: with htmx), the new form \nfields will not be initialized as django-tomselect fields. In order to manually \ninitialize them, dispatch a `triggerTomSelect` event, providing the id of the \nform field as a value in `detail` as follows.\n\n```javascript\n<script>\n  window.dispatchEvent(new CustomEvent('triggerTomSelect', {\n    detail: {\n        elemID: 'id_tomselect_tabular'\n    }\n  }));\n</script>\n````\n\n---\n\n## Development & Demo\n\n```bash\npython3 -m venv venv\nsource venv/bin/activate\nmake init\n```\n\nThen see the demo for a preview: `python demo/manage.py runserver`\n\nRun tests with `make test` or `make tox`. To install required browsers for playwright: `playwright install`.\nSee the makefile for other commands.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Django autocomplete widgets and views using Tom Select",
    "version": "0.4.4",
    "project_urls": {
        "Source": "https://github.com/jacklinke/django-tomselect"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1d4ac81042525b1a88a412456a5ae3eaf72299114b0b43e2d5dddd1032371403",
                "md5": "75818525d60b1aa0ec69dc31251ba771",
                "sha256": "0052cd38112e7621617f7af82aa492c15086047c049706e238305bb4e0dfa459"
            },
            "downloads": -1,
            "filename": "django_tomselect-0.4.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "75818525d60b1aa0ec69dc31251ba771",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 61699,
            "upload_time": "2023-10-10T01:53:22",
            "upload_time_iso_8601": "2023-10-10T01:53:22.183966Z",
            "url": "https://files.pythonhosted.org/packages/1d/4a/c81042525b1a88a412456a5ae3eaf72299114b0b43e2d5dddd1032371403/django_tomselect-0.4.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "942ff45a4ff04eb457812ba77022fdf1a4b4578e65b43e69c29b1c9f346e8c99",
                "md5": "c90cae2c20bfc72c55038c1ed40cd6a6",
                "sha256": "e11acc5cb93e9e254c06ce2283fd9f17f326b42be51feb53235ded5e7472323b"
            },
            "downloads": -1,
            "filename": "django-tomselect-0.4.4.tar.gz",
            "has_sig": false,
            "md5_digest": "c90cae2c20bfc72c55038c1ed40cd6a6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 66839,
            "upload_time": "2023-10-10T01:53:25",
            "upload_time_iso_8601": "2023-10-10T01:53:25.950105Z",
            "url": "https://files.pythonhosted.org/packages/94/2f/f45a4ff04eb457812ba77022fdf1a4b4578e65b43e69c29b1c9f346e8c99/django-tomselect-0.4.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-10 01:53:25",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jacklinke",
    "github_project": "django-tomselect",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "Django",
            "specs": [
                [
                    "~=",
                    "4.2"
                ]
            ]
        },
        {
            "name": "coverage",
            "specs": [
                [
                    "~=",
                    "7.3"
                ]
            ]
        },
        {
            "name": "tox",
            "specs": [
                [
                    "~=",
                    "4.10"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "~=",
                    "7.4"
                ]
            ]
        },
        {
            "name": "pytest-django",
            "specs": [
                [
                    "~=",
                    "4.5"
                ]
            ]
        },
        {
            "name": "pytest-xdist",
            "specs": [
                [
                    "~=",
                    "3.3"
                ]
            ]
        },
        {
            "name": "pytest-cov",
            "specs": [
                [
                    "~=",
                    "4.1"
                ]
            ]
        },
        {
            "name": "pytest-playwright",
            "specs": [
                [
                    "~=",
                    "0.4"
                ]
            ]
        },
        {
            "name": "playwright",
            "specs": [
                [
                    "~=",
                    "1.37"
                ]
            ]
        },
        {
            "name": "black",
            "specs": [
                [
                    "~=",
                    "23.7"
                ]
            ]
        },
        {
            "name": "ruff",
            "specs": [
                [
                    "==",
                    "0.0.292"
                ]
            ]
        },
        {
            "name": "build",
            "specs": [
                [
                    "~=",
                    "0.10"
                ]
            ]
        },
        {
            "name": "twine",
            "specs": [
                [
                    "~=",
                    "4.0"
                ]
            ]
        }
    ],
    "tox": true,
    "lcname": "django-tomselect"
}
        
Elapsed time: 0.19485s