import binascii from django.core.exceptions import ValidationError from django.forms import CharField, Field, MultipleChoiceField from django.utils.translation import gettext_lazy as _ from graphql_relay import from_global_id class GlobalIDFormField(Field): default_error_messages = {"invalid": _("Invalid ID specified.")} def clean(self, value): if not value and not self.required: return None try: _type, _id = from_global_id(value) except (TypeError, ValueError, UnicodeDecodeError, binascii.Error): raise ValidationError(self.error_messages["invalid"]) try: CharField().clean(_id) CharField().clean(_type) except ValidationError: raise ValidationError(self.error_messages["invalid"]) return value class GlobalIDMultipleChoiceField(MultipleChoiceField): default_error_messages = { "invalid_choice": _("One of the specified IDs was invalid (%(value)s)."), "invalid_list": _("Enter a list of values."), } def valid_value(self, value): # Clean will raise a validation error if there is a problem GlobalIDFormField().clean(value) return True