feat(fields:forms:dynamic-select): support existing objects not currently on the queryset

and add create_field to DynamicModelChoiceField
This commit is contained in:
Herculino Trotta
2025-01-04 17:59:59 -03:00
parent eb753bb30e
commit 7a759be357
+15 -7
View File
@@ -8,6 +8,12 @@ from apps.common.widgets.tom_select import TomSelect, TomSelectMultiple
class DynamicModelChoiceField(forms.ModelChoiceField): class DynamicModelChoiceField(forms.ModelChoiceField):
def __init__(self, model, *args, **kwargs): def __init__(self, model, *args, **kwargs):
self.model = model self.model = model
self.to_field_name = kwargs.pop("to_field_name", "pk")
self.create_field = kwargs.pop("create_field", None)
if not self.create_field:
raise ValueError("The 'create_field' parameter is required.")
self.queryset = kwargs.pop("queryset", model.objects.all()) self.queryset = kwargs.pop("queryset", model.objects.all())
super().__init__(queryset=self.queryset, *args, **kwargs) super().__init__(queryset=self.queryset, *args, **kwargs)
self._created_instance = None self._created_instance = None
@@ -18,8 +24,7 @@ class DynamicModelChoiceField(forms.ModelChoiceField):
if value in self.empty_values: if value in self.empty_values:
return None return None
try: try:
key = self.to_field_name or "pk" return self.model.objects.get(**{self.to_field_name: value})
return self.model.objects.get(**{key: value})
except (ValueError, TypeError, self.model.DoesNotExist): except (ValueError, TypeError, self.model.DoesNotExist):
return value # Return the raw value; we'll handle creation in clean() return value # Return the raw value; we'll handle creation in clean()
@@ -49,10 +54,13 @@ class DynamicModelChoiceField(forms.ModelChoiceField):
except self.model.DoesNotExist: except self.model.DoesNotExist:
try: try:
with transaction.atomic(): with transaction.atomic():
instance = self.model.objects.create(name=value) instance, _ = self.model.objects.update_or_create(
**{self.create_field: value}
)
self._created_instance = instance self._created_instance = instance
return instance return instance
except Exception as e: except Exception as e:
print(e)
raise ValidationError( raise ValidationError(
self.error_messages["invalid_choice"], code="invalid_choice" self.error_messages["invalid_choice"], code="invalid_choice"
) )
@@ -111,10 +119,10 @@ class DynamicModelMultipleChoiceField(forms.ModelMultipleChoiceField):
""" """
try: try:
with transaction.atomic(): with transaction.atomic():
new_instance = self.queryset.model(**{self.create_field: value}) instance, _ = self.model.objects.update_or_create(
new_instance.full_clean() **{self.create_field: value}
new_instance.save() )
return new_instance return instance
except Exception as e: except Exception as e:
raise ValidationError(f"Error creating new instance: {str(e)}") raise ValidationError(f"Error creating new instance: {str(e)}")