Closes #5858: Implement a quick-add UI widget for related objects (#18016)

* WIP

* Misc cleanup

* Add warning re: nested quick-adds
This commit is contained in:
Jeremy Stretch
2024-11-18 14:44:57 -05:00
committed by GitHub
parent 9fe6685562
commit b4f15092db
17 changed files with 236 additions and 76 deletions

View File

@@ -2,7 +2,7 @@ import django_filters
from django import forms
from django.conf import settings
from django.forms import BoundField
from django.urls import reverse
from django.urls import reverse, reverse_lazy
from utilities.forms import widgets
from utilities.views import get_viewname
@@ -66,6 +66,8 @@ class DynamicModelChoiceMixin:
choice (DEPRECATED: pass `context={'disabled': '$fieldname'}` instead)
context: A mapping of <option> template variables to their API data keys (optional; see below)
selector: Include an advanced object selection widget to assist the user in identifying the desired object
quick_add: Include a widget to quickly create a new related object for assignment. NOTE: Nested usage of
quick-add fields is not currently supported.
Context keys:
value: The name of the attribute which contains the option's value (default: 'id')
@@ -90,6 +92,7 @@ class DynamicModelChoiceMixin:
disabled_indicator=None,
context=None,
selector=False,
quick_add=False,
**kwargs
):
self.model = queryset.model
@@ -99,6 +102,7 @@ class DynamicModelChoiceMixin:
self.disabled_indicator = disabled_indicator
self.context = context or {}
self.selector = selector
self.quick_add = quick_add
super().__init__(queryset, **kwargs)
@@ -121,6 +125,12 @@ class DynamicModelChoiceMixin:
if self.selector:
attrs['selector'] = self.model._meta.label_lower
# Include quick add?
if self.quick_add:
app_label = self.model._meta.app_label
model_name = self.model._meta.model_name
attrs['quick_add'] = reverse_lazy(f'{app_label}:{model_name}_add')
return attrs
def get_bound_field(self, form, field_name):

View File

@@ -1,7 +1,8 @@
{% load i18n %}
{% if widget.attrs.selector and not widget.attrs.disabled %}
<div class="d-flex">
{% include 'django/forms/widgets/select.html' %}
<div class="d-flex">
{% include 'django/forms/widgets/select.html' %}
{% if widget.attrs.selector and not widget.attrs.disabled %}
{# Opens the object selector modal #}
<button
type="button"
title="{% trans "Open selector" %}"
@@ -13,7 +14,19 @@
>
<i class="mdi mdi-database-search-outline"></i>
</button>
</div>
{% else %}
{% include 'django/forms/widgets/select.html' %}
{% endif %}
{% endif %}
{% if widget.attrs.quick_add and not widget.attrs.disabled %}
{# Opens the quick add modal #}
<button
type="button"
title="{% trans "Quick add" %}"
class="btn btn-outline-secondary ms-1"
data-bs-toggle="modal"
data-bs-target="#htmx-modal"
hx-get="{{ widget.attrs.quick_add }}?_quickadd=True&target={{ widget.attrs.id }}"
hx-target="#htmx-modal-content"
>
<i class="mdi mdi-plus-circle"></i>
</button>
{% endif %}
</div>