Address PR feedback: Move FORM_FIELD_LOOKUPS to module-level constant

Extracts the field type to lookup mappings from FilterModifierMixin class
attribute to a module-level constant for better reusability.
This commit is contained in:
Jason Novinger 2025-11-20 05:30:29 -06:00
parent 05e1317f5e
commit ac74d9f9be

View File

@ -13,82 +13,10 @@ __all__ = (
'CheckLastUpdatedMixin',
'DistanceValidationMixin',
'FilterModifierMixin',
'FORM_FIELD_LOOKUPS',
)
class BackgroundJobMixin(forms.Form):
background_job = forms.BooleanField(
label=_('Background job'),
help_text=_("Execute this task via a background job"),
required=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Declare background_job a meta field
if hasattr(self, 'meta_fields'):
self.meta_fields.append('background_job')
else:
self.meta_fields = ['background_job']
class CheckLastUpdatedMixin(forms.Form):
"""
Checks whether the object being saved has been updated since the form was initialized. If so, validation fails.
This prevents a user from inadvertently overwriting any changes made to the object between when the form was
initialized and when it was submitted.
This validation does not apply to newly created objects, or if the `_init_time` field is not present in the form
data.
"""
_init_time = forms.DecimalField(
initial=time.time,
required=False,
widget=forms.HiddenInput()
)
def clean(self):
super().clean()
# Skip for absent or newly created instances
if not self.instance or not self.instance.pk:
return
# Skip if a form init time has not been specified
if not (form_init_time := self.cleaned_data.get('_init_time')):
return
# Skip if the object does not have a last_updated value
if not (last_updated := getattr(self.instance, 'last_updated', None)):
return
# Check that the submitted initialization time is not earlier than the object's modification time
if form_init_time < last_updated.timestamp():
raise forms.ValidationError(_(
"This object has been modified since the form was rendered. Please consult the object's change "
"log for details."
))
class DistanceValidationMixin(forms.Form):
distance = forms.DecimalField(
required=False,
validators=[
MinValueValidator(Decimal(0)),
MaxValueValidator(Decimal(100000)),
]
)
class FilterModifierMixin:
"""
Mixin that enhances filter form fields with lookup modifier dropdowns.
Automatically detects fields that could benefit from multiple lookup options
and wraps their widgets with FilterModifierWidget.
"""
# Mapping of form field types to their supported lookups
FORM_FIELD_LOOKUPS = {
forms.CharField: [
@ -165,6 +93,80 @@ class FilterModifierMixin:
],
}
class BackgroundJobMixin(forms.Form):
background_job = forms.BooleanField(
label=_('Background job'),
help_text=_("Execute this task via a background job"),
required=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Declare background_job a meta field
if hasattr(self, 'meta_fields'):
self.meta_fields.append('background_job')
else:
self.meta_fields = ['background_job']
class CheckLastUpdatedMixin(forms.Form):
"""
Checks whether the object being saved has been updated since the form was initialized. If so, validation fails.
This prevents a user from inadvertently overwriting any changes made to the object between when the form was
initialized and when it was submitted.
This validation does not apply to newly created objects, or if the `_init_time` field is not present in the form
data.
"""
_init_time = forms.DecimalField(
initial=time.time,
required=False,
widget=forms.HiddenInput()
)
def clean(self):
super().clean()
# Skip for absent or newly created instances
if not self.instance or not self.instance.pk:
return
# Skip if a form init time has not been specified
if not (form_init_time := self.cleaned_data.get('_init_time')):
return
# Skip if the object does not have a last_updated value
if not (last_updated := getattr(self.instance, 'last_updated', None)):
return
# Check that the submitted initialization time is not earlier than the object's modification time
if form_init_time < last_updated.timestamp():
raise forms.ValidationError(_(
"This object has been modified since the form was rendered. Please consult the object's change "
"log for details."
))
class DistanceValidationMixin(forms.Form):
distance = forms.DecimalField(
required=False,
validators=[
MinValueValidator(Decimal(0)),
MaxValueValidator(Decimal(100000)),
]
)
class FilterModifierMixin:
"""
Mixin that enhances filter form fields with lookup modifier dropdowns.
Automatically detects fields that could benefit from multiple lookup options
and wraps their widgets with FilterModifierWidget.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._enhance_fields_with_modifiers()
@ -217,8 +219,8 @@ class FilterModifierMixin:
"""Determine the available lookup choices for a given field."""
# Walk up the MRO to find a known field type
for field_class in field.__class__.__mro__:
if field_class in self.FORM_FIELD_LOOKUPS:
return self.FORM_FIELD_LOOKUPS[field_class]
if field_class in FORM_FIELD_LOOKUPS:
return FORM_FIELD_LOOKUPS[field_class]
# Unknown field type - return single exact option (no enhancement)
return [('exact', _('Is'))]