EmptyModelChoiceField

Format: Python
 ( View Raw)
Date: Sun, 24 Sep 2023 at 16:38:49

from django import forms
from django.core.exceptions import ValidationError


class EmptyModelChoiceField(forms.ModelChoiceField):
    """
    This ModelChoiceField is used for empty or partial querysets.
    When the form field is validated, ignore the item is not found in the
    queryset.
    The item will be searched again during the validation in the manager
    object instead of using the queryset
    """
    def __init__(self, queryset, manager, *, empty_label="---------",
                 required=True, widget=None, label=None, initial=None,
                 help_text='', to_field_name=None, limit_choices_to=None,
                 blank=False, **kwargs):
        super().__init__(queryset=queryset,
                         empty_label=empty_label,
                         required=required,
                         widget=widget,
                         label=label,
                         initial=initial,
                         help_text=help_text,
                         to_field_name=to_field_name,
                         limit_choices_to=limit_choices_to,
                         blank=blank,
                         **kwargs)
        # Manager object to use for future lookups
        self.manager = manager

    def to_python(self, value):
        try:
            value = super().to_python(value)
        except ValidationError as error:
            # Item not found
            key = self.to_field_name or 'pk'
            # Search again using the the manager object
            value = self.manager.filter(**{key: value})
            if value.exists():
                # Item was found in the manager object
                value = value.first()
            else:
                # Item was not found in the manager object
                # Raise the same parent class ValidationError
                raise error
        return value