text: import copy
  from typing import Any, Tuple, Union
  
  from django.forms import Select
  from django.forms.fields import CallableChoiceIterator, Field
  from django.utils.translation import gettext_lazy as _
  
  
  class AjaxChoiceField(Field):
      widget = Select
      default_error_messages = {
          'invalid_choice': _('Select a valid choice. %(value)s is not one of the available choices.'),
      }
  
      def __init__(self, *, choices: Tuple = (), **kwargs: Any) -> None:
          super().__init__(**kwargs)
          self.choices = choices
  
      def __deepcopy__(self, memo: dict) -> Field:
          result = super().__deepcopy__(memo)
          result._choices = copy.deepcopy(self._choices, memo)
          return result
  
      def _get_choices(self) -> Union[CallableChoiceIterator, list]:
          return self._choices
  
      def _set_choices(self, value: Any) -> None:
          # Setting choices also sets the choices on the widget.
          # choices can be any iterable, but we call list() on it because
          # it will be consumed more than once.
          if callable(value):
              value = CallableChoiceIterator(value)
          else:
              value = list(value)
  
          self._choices = self.widget.choices = value
  
      choices = property(_get_choices, _set_choices)
  
      def to_python(self, value: Any) -> str:
          """Return a string."""
          if value in self.empty_values:
              return ''
          return str(value)
  
      def validate(self, value: Any) -> None:
          """Validate that the input is in self.choices."""
          super().validate(value)
  
      def valid_value(self, value: Any) -> bool:
          """Check to see if the provided value is a valid choice."""
          text_value = str(value)
          for k, v in self.choices:
              if isinstance(v, (list, tuple)):
                  # This is an optgroup, so look inside the group for options
                  for k2, v2 in v:
                      if value == k2 or text_value == str(k2):
                          return True
              else:
                  if value == k or text_value == str(k):
                      return True
          return False
  