Refactor UserUserGroupForm to use a reusable UserSearchSelectMultipleWidget for improved user selection and search functionality
This commit is contained in:
+13
-14
@@ -556,20 +556,16 @@ class UserUserGroupModelChoiceField(ModelMultipleChoiceField):
|
||||
return f"{obj.username} ({obj.userprofile.grade}) [{obj.email}]"
|
||||
|
||||
|
||||
class UserUserGroupForm(ModelForm):
|
||||
class UserSearchSelectMultiple(object):
|
||||
"""
|
||||
Lightweight widget renderer for a searchable multi-user selector.
|
||||
Renders a hidden <select multiple> containing selected user ids and
|
||||
a search box with results. Uses a small inline script to fetch
|
||||
results from the `generic:user_search_widget` endpoint and add/remove
|
||||
users from the selection.
|
||||
This keeps implementation simple and avoids external JS dependencies.
|
||||
class UserSearchSelectMultipleWidget:
|
||||
"""Reusable lightweight widget renderer for a searchable multi-user selector.
|
||||
|
||||
Usage: instantiate with (name, value) where value is an iterable of user ids
|
||||
and call .render() to get the HTML fragment. This mirrors the previous
|
||||
nested widget but is available module-wide for reuse.
|
||||
"""
|
||||
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
# value is a list of selected user ids
|
||||
self.value = value or []
|
||||
|
||||
def render(self):
|
||||
@@ -578,13 +574,11 @@ class UserUserGroupForm(ModelForm):
|
||||
results_id = f"user_search_results_{self.name}"
|
||||
selected_list_id = f"selected_users_{self.name}"
|
||||
|
||||
# Build initial options for selected users
|
||||
users = User.objects.filter(pk__in=self.value) if self.value else []
|
||||
options_html = ""
|
||||
selected_html = ""
|
||||
for u in users:
|
||||
options_html += f'<option value="{u.pk}" selected>{u.get_full_name() or u.username} - {u.email}</option>'
|
||||
# include grade display in the selected list if available
|
||||
grade_text = ""
|
||||
try:
|
||||
up = getattr(u, "userprofile", None)
|
||||
@@ -605,10 +599,10 @@ class UserUserGroupForm(ModelForm):
|
||||
|
||||
url = reverse("generic:user_search_widget")
|
||||
|
||||
# Build a small grade filter select
|
||||
grades_options = '<option value="">All grades</option>'
|
||||
try:
|
||||
from generic.models import UserGrades
|
||||
|
||||
grades_qs = UserGrades.objects.all()
|
||||
for g in grades_qs:
|
||||
grades_options += f'<option value="{g.pk}">{g.name}</option>'
|
||||
@@ -776,6 +770,11 @@ class UserUserGroupForm(ModelForm):
|
||||
|
||||
return mark_safe(html)
|
||||
|
||||
|
||||
|
||||
class UserUserGroupForm(ModelForm):
|
||||
# Use module-level UserSearchSelectMultipleWidget for rendering the users field
|
||||
|
||||
users = UserUserGroupModelChoiceField(
|
||||
required=False,
|
||||
queryset=User.objects.all(),
|
||||
@@ -808,7 +807,7 @@ class UserUserGroupForm(ModelForm):
|
||||
# store attrs so template helpers can inspect them
|
||||
self.attrs = attrs or {}
|
||||
value = value or []
|
||||
widget = UserUserGroupForm.UserSearchSelectMultiple(name, value)
|
||||
widget = UserSearchSelectMultipleWidget(name, value)
|
||||
return widget.render()
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
|
||||
Reference in New Issue
Block a user