class RegistrarEditForm(EditForm): def __init__(self, *args, **kwargs): super(RegistrarEditForm, self).__init__( layout_class=RegistrarEditFormLayout, enctype="multipart/form-data", *args, **kwargs) id = HiddenDecimalField() handle = CharField(label=_('Handle')) # registrar identification name = CharField(label=_('Name'), required=False) # registrar name organization = CharField(label=_('Organization'), required=False) # organization name street1 = CharField(label=_('Street1'), required=False) # address part 1 street2 = CharField(label=_('Street2'), required=False) # address part 2 street3 = CharField(label=_('Street3'), required=False) # address part 3 city = CharField(label=_('City'), required=False) # city of registrar headquaters stateorprovince = CharField(label=_('State'), required=False) # address part postalcode = CharField(label=_('ZIP'), required=False, max_length=32) # address part country = ChoiceField( label=_('Country'), choices=CorbaLazyRequestIterStruct( 'Admin', None, 'getCountryDescList', ['cc', 'name'], None), initial=CorbaLazyRequest('Admin', None, 'getDefaultCountry', None), required=False) # country code ico = CharField(label=_('ICO'), required=False, max_length=50) dic = CharField(label=_('DIC'), required=False, max_length=50) varSymb = CharField(label=_('Var. Symbol'), required=False, max_length=10) vat = BooleanField(label=_('DPH'), required=False) telephone = CharField(label=_('Telephone'), required=False, max_length=32) # phne number fax = CharField(label=_('Fax'), required=False, max_length=32) # fax number email = CharField(label=_('Email'), required=False) # contact email url = CharField(label=_('URL'), required=False) # URL hidden = BooleanField(label=_('System registrar'), required=False) # System registrar visible_fieldsets_ids = HiddenField( required=False, id="visible_fieldsets_ids_field_id") access = FormSetField( label=_('Authentication'), form_class=AccessEditForm, can_delete=True, formset_layout=DivFormSetLayout) zones = FormSetField( label=_('Zones'), form_class=ZoneEditForm, can_delete=False, formset_layout=DivFormSetLayout) groups = FormSetField( label=_('Groups'), form_class=SingleGroupEditForm, can_delete=True) certifications = FormSetField( label=_('Certifications'), form_class=CertificationEditForm, can_delete=False) sections = ( (_("Registrar data"), ("registrar_data_id"), ( "handle", "name", "organization", 'street1', 'street2', 'street3', 'city', 'postalcode', 'stateorprovince', 'country', "postalCode", "ico", "dic", "varSymb", "vat", "telephone", "fax", "email", "url", "hidden", "id", "visible_fieldsets_ids"), HideableSimpleFieldsetFormSectionLayout), (_("Authentication"), ("authentications_id"), ("access"), HideableNestedFieldsetFormSectionLayout), (_("Zones"), ("zones_id"), ("zones"), HideableNestedFieldsetFormSectionLayout), (_("Groups"), ("groups_id"), ("groups"), HideableNestedFieldsetFormSectionLayout), (_("Certifications"), ("certifications_id"), ("certifications"), HideableNestedFieldsetFormSectionLayout)) def filter_base_fields(self): """ Filters base fields against user negative permissions, so if the user has nperm on the field we delete it from base_fields. """ if self.nperm_names: user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: object_name = self.get_object_name() formset_fields = [ self.base_fields['access'], self.base_fields['zones'], self.base_fields['groups'], self.base_fields['certifications']] for field in formset_fields: if not user.check_nperms(['%s.%s.%s' % ( nperm_name, object_name, field.get_nperm()) for nperm_name in self.nperm_names], 'one'): field.permitted = True else: field.permitted = False filtered_base_fields = SortedDict( [(name, field) for name, field in self.base_fields.items()] ) self.base_fields = filtered_base_fields def fire_actions(self, *args, **kwargs): try: reg = kwargs["updated_registrar"] except KeyError: raise RuntimeError( "RegistrarDataEditForm: Failed to fetch " "updated registrar from kwargs.") session = utils.get_corba_session() try: reg_id = session.updateRegistrar(reg) except ccReg.Admin.UpdateFailed, e: raise UpdateFailedError( "Updating registrar failed. Perhaps you tried to " "create a registrar with an already used handle?") # Set created/updated registrar id to result (it is used in ADIF # registrar page and other fire_action methods). kwargs["result"]['reg_id'] = reg_id # Fire actions for groups. self.fields["groups"].fire_actions(reg_id=reg_id, *args, **kwargs) self.fields["certifications"].fire_actions( reg_id=reg_id, *args, **kwargs)
class BaseDetail(div): editable = False nperm_names = ['read'] def __init__(self, data, history, label_suffix=':', display_only=None, sections=None, layout_class=SectionDetailLayout, is_nested=False, all_no_access=False, *content, **kwd): super(BaseDetail, self).__init__(*content, **kwd) self.tag = u'' self.media_files.append('/css/details.css') self.history = history self.data = data or {} if data is not None: if not isinstance(data, types.DictType): # data is some corba object self.data = data.__dict__ else: # data is dict self.data = data self.label_suffix = label_suffix self.layout_class = layout_class self.is_nested = is_nested self.all_no_access = all_no_access # check if display_only contains correct field names if display_only: for field_name in display_only: if self.base_fields.get(field_name) is None: raise RuntimeError( _('Incorrect field name "%s" specified in %s. display_only list!' ) % (field_name, repr(self))) self.display_only = display_only # Sections can be defined as class attribute of detail, so take care # to create attribute but not override it, if it already exists. if getattr(self, 'sections', None) is None: self.sections = None if sections is not None: self.sections = sections self.fields = None self.filter_base_fields() self.build_fields() self.set_fields_values() # if self.section is None, create one default section with all fields: if self.sections is None or sections == 'all_in_one': self.sections = [[None, self.fields.keys()]] def filter_base_fields(self): """ Filters base fields against user negative permissions, so if user has nperm on field we delete it from base_fields. """ user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: self.base_fields = SortedDict([ (name, field) for name, field in self.base_fields.items() if not self.display_only or field.name in self.display_only ]) def build_fields(self): user = cherrypy.session.get('user', None) if user is None: self.fields = SortedDict({}) else: self.fields = self.base_fields.deepcopy() object_name = self.get_object_name() for field in self.fields.values(): field_nperm = field.get_nperm() if self.all_no_access or user.check_nperms( ['%s.%s.%s' % (nperm_name, object_name, field_nperm) for \ nperm_name in self.nperm_names], 'one'): field.access = False field.owner_detail = self def set_fields_values(self): for field in self.fields.values(): field.value = field.value_from_data(self.data) @classmethod def get_object_name(cls): return cls.__name__[:-len('Detail')].lower() def add_to_bottom(self): ''' Usualy used for filterpanel and/or edit link. ''' if self.editable: self.add( p( a( attr(href=u'../edit/?id=' + unicode(self.data.get('id'))), _('Edit')))) def render(self, indent_level=0): self.content = [ ] # empty previous content (if render would be called moretimes, there would be multiple forms instead one ) self.add(self.layout_class(self)) if self.check_nperms(): # TODO: render error! return div("ERROR NO PERMS").render() pass if not self.is_nested: self.add_to_bottom() return super(BaseDetail, self).render(indent_level) def check_nperms(self): return False @classmethod def get_nperms(cls): nperms = [] for field in cls.base_fields.values(): field_nperm = field.get_nperm() field_nperms = [ '%s.%s.%s' % (nperm_name, cls.get_object_name(), field_nperm) for nperm_name in cls.nperm_names ] nperms.extend(field_nperms) return nperms
class RegistrarEditForm(EditForm): def __init__(self, *args, **kwargs): super(RegistrarEditForm, self).__init__(layout_class=RegistrarEditFormLayout, enctype="multipart/form-data", *args, **kwargs) handle = CharField(label=_('Handle')) # registrar identification name = CharField(label=_('Name'), required=False) # registrar name organization = CharField(label=_('Organization'), required=False) # organization name street1 = CharField(label=_('Street1'), required=False) # address part 1 street2 = CharField(label=_('Street2'), required=False) # address part 2 street3 = CharField(label=_('Street3'), required=False) # address part 3 city = CharField(label=_('City'), required=False) # city of registrar headquaters stateorprovince = CharField(label=_('State'), required=False) # address part postalcode = CharField(label=_('ZIP'), required=False, max_length=32) # address part country = ChoiceField(label=_('Country'), choices=CorbaLazyRequestIterStruct( 'Admin', None, 'getCountryDescList', ['cc', 'name'], None), initial=CorbaLazyRequest('Admin', None, 'getDefaultCountry', None), required=False) # country code ico = CharField(label=_('ICO'), required=False, max_length=50) dic = CharField(label=_('DIC'), required=False, max_length=50) varSymb = CharField(label=_('Var. Symbol'), required=False, max_length=10) vat = BooleanField(label=_('DPH'), required=False) telephone = CharField(label=_('Telephone'), required=False, max_length=32) # phne number fax = CharField(label=_('Fax'), required=False, max_length=32) # fax number email = CharField(label=_('Email'), required=False) # contact email url = CharField(label=_('URL'), required=False) # URL hidden = BooleanField(label=_('System registrar'), required=False) # System registrar visible_fieldsets_ids = HiddenField(required=False, id="visible_fieldsets_ids_field_id") access = FormSetField(label=_('Authentication'), form_class=AccessEditForm, can_delete=True, formset_layout=DivFormSetLayout) zones = FormSetField(label=_('Zones'), form_class=ZoneEditForm, can_delete=False, formset_layout=DivFormSetLayout) groups = FormSetField(label=_('Groups'), form_class=SingleGroupEditForm, can_delete=True) certifications = FormSetField(label=_('Certifications'), form_class=CertificationEditForm, can_delete=False) sections = ((_("Registrar data"), ("registrar_data_id"), ("handle", "name", "organization", 'street1', 'street2', 'street3', 'city', 'postalcode', 'stateorprovince', 'country', "postalCode", "ico", "dic", "varSymb", "vat", "telephone", "fax", "email", "url", "hidden", "id", "visible_fieldsets_ids"), HideableSimpleFieldsetFormSectionLayout), (_("Authentication"), ("authentications_id"), ("access"), HideableNestedFieldsetFormSectionLayout), (_("Zones"), ("zones_id"), ("zones"), HideableNestedFieldsetFormSectionLayout), (_("Groups"), ("groups_id"), ("groups"), HideableNestedFieldsetFormSectionLayout), (_("Certifications"), ("certifications_id"), ("certifications"), HideableNestedFieldsetFormSectionLayout)) def filter_base_fields(self): """ Filters base fields against user negative permissions, so if the user has nperm on the field we delete it from base_fields. """ if self.nperm_names: user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: object_name = self.get_object_name() formset_fields = [ self.base_fields['access'], self.base_fields['zones'], self.base_fields['groups'], self.base_fields['certifications'] ] for field in formset_fields: if not user.check_nperms([ '%s.%s.%s' % (nperm_name, object_name, field.get_nperm()) for nperm_name in self.nperm_names ], 'one'): field.permitted = True else: field.permitted = False filtered_base_fields = SortedDict([ (name, field) for name, field in self.base_fields.items() ]) self.base_fields = filtered_base_fields def fire_actions(self, *args, **kwargs): try: reg = kwargs["updated_registrar"] except KeyError: raise RuntimeError("RegistrarDataEditForm: Failed to fetch " "updated registrar from kwargs.") session = utils.get_corba_session() try: reg_id = session.updateRegistrar(reg) except ccReg.Admin.UpdateFailed: raise UpdateFailedError( "Updating registrar failed. Perhaps you tried to " "create a registrar with an already used handle or variable symbol?" ) # Set created/updated registrar id to result (it is used in ADIF # registrar page and other fire_action methods). kwargs["result"]['reg_id'] = reg_id # Fire actions for groups. self.fields["groups"].fire_actions(reg_id=reg_id, *args, **kwargs) self.fields["certifications"].fire_actions(reg_id=reg_id, *args, **kwargs)
class BaseDetail(div): editable = False nperm_names = ['read'] def __init__(self, data, history, label_suffix=':', display_only = None, sections = None, layout_class=SectionDetailLayout, is_nested = False, all_no_access=False, *content, **kwd): super(BaseDetail, self).__init__(*content, **kwd) self.tag = u'' self.media_files.append('/css/details.css') self.history = history self.data = data or {} if data is not None: if not isinstance(data, types.DictType): # data is some corba object self.data = data.__dict__ else: # data is dict self.data = data self.label_suffix = label_suffix self.layout_class = layout_class self.is_nested = is_nested self.all_no_access = all_no_access # check if display_only contains correct field names if display_only: for field_name in display_only: if self.base_fields.get(field_name) is None: raise RuntimeError(_('Incorrect field name "%s" specified in %s. display_only list!') % (field_name, repr(self))) self.display_only = display_only # Sections can be defined as class attribute of detail, so take care # to create attribute but not override it, if it already exists. if getattr(self, 'sections', None) is None: self.sections = None if sections is not None: self.sections = sections self.fields = None self.filter_base_fields() self.build_fields() self.set_fields_values() # if self.section is None, create one default section with all fields: if self.sections is None or sections == 'all_in_one': self.sections = [[None, self.fields.keys()]] def filter_base_fields(self): """ Filters base fields against user negative permissions, so if user has nperm on field we delete it from base_fields. """ user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: self.base_fields = SortedDict( [(name, field) for name, field in self.base_fields.items() if not self.display_only or field.name in self.display_only]) def build_fields(self): user = cherrypy.session.get('user', None) if user is None: self.fields = SortedDict({}) else: self.fields = self.base_fields.deepcopy() object_name = self.get_object_name() for field in self.fields.values(): field_nperm = field.get_nperm() if self.all_no_access or user.check_nperms( ['%s.%s.%s' % (nperm_name, object_name, field_nperm) for \ nperm_name in self.nperm_names], 'one'): field.access = False field.owner_detail = self def set_fields_values(self): for field in self.fields.values(): if field.access: field.value = field.value_from_data(self.data) else: field.value = field.value_from_data({}) # emtpy dict as there are no data field.make_content_no_access() @classmethod def get_object_name(cls): return cls.__name__[:-len('Detail')].lower() def add_to_bottom(self): ''' Usualy used for filterpanel and/or edit link. ''' if self.editable: self.add(p(a(attr(href=u'../edit/?id=' + unicode(self.data.get('id'))), _('Edit')))) def render(self, indent_level=0): self.content = [] # empty previous content (if render would be called moretimes, there would be multiple forms instead one ) self.add(self.layout_class(self)) if self.check_nperms(): # TODO: render error! return div("ERROR NO PERMS").render() pass if not self.is_nested: self.add_to_bottom() return super(BaseDetail, self).render(indent_level) def check_nperms(self): return False @classmethod def get_nperms(cls): nperms = [] for field in cls.base_fields.values(): field_nperm = field.get_nperm() field_nperms = ['%s.%s.%s' % (nperm_name, cls.get_object_name(), field_nperm) for nperm_name in cls.nperm_names] nperms.extend(field_nperms) return nperms
class BaseForm(form): # This is the main implementation of all the Form logic. Note that this # class is different than Form. See the comments by the Form class for more # information. Any improvements to the form API should be made to *this* # class, not to the Form class nperm_names = [] name_postfix = '' _submit_button_text = 'OK' def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, label_suffix=':', layout_class=TableFormLayout, submit_button_text=None, is_nested=False, empty_permitted=False, *content, **kwd): super(BaseForm, self).__init__(*content, **kwd) if not is_nested: self.tag = u'form' else: self.tag = u'' self.is_bound = data is not None or files is not None self.data = data or {} self.files = files or {} self.auto_id = auto_id self.prefix = prefix self.initial = initial or {} self.error_class = error_class self.label_suffix = label_suffix self._errors = None # Stores the errors after clean() has been called. self.layout_class = layout_class self.is_nested = is_nested if submit_button_text is not None: self._submit_button_text = submit_button_text self.empty_permitted = empty_permitted self._changed_data = None # The base_fields class attribute is the *class-wide* definition of # fields. Because a particular *instance* of the class might want to # alter self.fields, we create self.fields here by copying base_fields. # Instances should always modify self.fields; they should not modify # self.base_fields. self.fields = None self.filter_base_fields() self.build_fields() self.set_fields_values() def filter_base_fields(self): """ Filters base fields against user negative permissions, so if the user has nperm on the field we delete it from base_fields. """ if self.nperm_names: user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: object_name = self.get_object_name() filtered_base_fields = SortedDict( [(name, field) for name, field in self.base_fields.items() if not user.check_nperms(['%s.%s.%s' % (nperm_name, object_name, field.get_nperm()) for nperm_name in self.nperm_names], 'one') ] ) self.base_fields = filtered_base_fields @classmethod def get_object_name(cls): return cls.__name__[:-len(cls.name_postfix)].lower() def build_fields(self): self.fields = self.base_fields.deepcopy() for field in self.fields.values(): field.owner_form = self field.name = self.add_prefix(field.name_orig) def set_fields_values(self): # setting initials is independent on whether form is bound or not: for field in self.fields.values(): data = self.initial.get(field.name_orig, field.initial) if callable(data): data = data() if data is not None: field.initial = data if not self.is_bound: if self.initial: for field in self.fields.values(): if field.initial is not None: field.value_is_from_initial = True field.value = field.initial else: for field in self.fields.values(): field.value = field.value_from_datadict(self.data) def __iter__(self): for field in self.fields.values(): yield field def __getitem__(self, name): "Returns a field with the given name." try: field = self.fields[name] except KeyError: raise KeyError('Key %r not found in Form' % name) return field def _get_errors(self): "Returns an ErrorDict for the data provided for the form" try: if self._errors is None: self.full_clean() return self._errors except AttributeError: raise RuntimeError('Camouflaged AttributeError from _get_errors, original error: \n %s' % unicode(traceback.format_exc())) errors = property(_get_errors) def is_valid(self): """ Returns True if the form has no errors. Otherwise, False. If errors are being ignored, returns False. """ return self.is_bound and not bool(self.errors) def add_prefix(self, field_name): """ Returns the field name with a prefix appended, if this Form has a prefix set. Subclasses may wish to override. """ return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name def render(self, indent_level=0): self.content = [] # empty previous content (if render would be called more times, there would be multiple forms instead one ) self.add(self.layout_class(self)) return super(BaseForm, self).render(indent_level) def non_field_errors(self): """ Returns an ErrorList of errors that aren't associated with a particular field - -i.e., from Form.clean(). Returns an empty ErrorList if there are none. """ result = self.errors.get(NON_FIELD_ERRORS, None) if not result: result = self.errors[NON_FIELD_ERRORS] = self.error_class() return result def is_empty(self, exceptions=None): """ Returns True if this form has been bound and all fields that aren't listed in exceptions are empty. """ # TODO: This could probably use some optimization exceptions = exceptions or [] for name, field in self.fields.items(): if name in exceptions: continue # value_from_datadict() gets the data from the dictionary. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. # HACK: ['', ''] and [None, None] deal with SplitDateTimeWidget. This should be more robust. if field.value not in (None, '', ['', ''], [None, None]): return False return True def full_clean(self): """ Cleans all of self.data and populates self._errors and self.cleaned_data. """ self._errors = ErrorDict() if not self.is_bound: # Stop further processing. return self.cleaned_data = {} if self.empty_permitted and not self.has_changed(): self.cleaned_data = None return for name, field in self.fields.items(): self.clean_field(name, field) try: self.cleaned_data = self.clean() except ValidationError, e: self._errors[NON_FIELD_ERRORS] = e.messages if self._errors: delattr(self, 'cleaned_data')
class BaseForm(form): # This is the main implementation of all the Form logic. Note that this # class is different than Form. See the comments by the Form class for more # information. Any improvements to the form API should be made to *this* # class, not to the Form class nperm_names = [] name_postfix = '' def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, label_suffix=':', layout_class=TableFormLayout, is_nested = False, empty_permitted=False, *content, **kwd): super(BaseForm, self).__init__(*content, **kwd) if not is_nested: self.tag = u'form' else: self.tag = u'' self.is_bound = data is not None or files is not None self.data = data or {} self.files = files or {} self.auto_id = auto_id self.prefix = prefix self.initial = initial or {} self.error_class = error_class self.label_suffix = label_suffix self._errors = None # Stores the errors after clean() has been called. self.layout_class = layout_class self.is_nested = is_nested self.empty_permitted = empty_permitted self._changed_data = None # The base_fields class attribute is the *class-wide* definition of # fields. Because a particular *instance* of the class might want to # alter self.fields, we create self.fields here by copying base_fields. # Instances should always modify self.fields; they should not modify # self.base_fields. self.fields = None self.filter_base_fields() self.build_fields() self.set_fields_values() def filter_base_fields(self): """ Filters base fields against user negative permissions, so if the user has nperm on the field we delete it from base_fields. """ if self.nperm_names: user = cherrypy.session.get('user', None) if user is None: self.base_fields = SortedDict({}) else: object_name = self.get_object_name() filtered_base_fields = SortedDict( [(name, field) for name, field in self.base_fields.items() if not user.check_nperms(['%s.%s.%s' % (nperm_name, object_name, field.get_nperm()) for nperm_name in self.nperm_names], 'one') ] ) self.base_fields = filtered_base_fields @classmethod def get_object_name(cls): return cls.__name__[:-len(cls.name_postfix)].lower() def build_fields(self): self.fields = self.base_fields.deepcopy() for field in self.fields.values(): field.owner_form = self field.name = self.add_prefix(field.name_orig) def set_fields_values(self): # setting initials is independent on whether form is bound or not: for field in self.fields.values(): data = self.initial.get(field.name_orig, field.initial) if callable(data): data = data() if data is not None: field.initial = data if not self.is_bound: if self.initial: for field in self.fields.values(): if field.initial is not None: field.value_is_from_initial = True field.value = field.initial else: for field in self.fields.values(): field.value = field.value_from_datadict(self.data) def __iter__(self): for field in self.fields.values(): yield field def __getitem__(self, name): "Returns a field with the given name." try: field = self.fields[name] except KeyError: raise KeyError('Key %r not found in Form' % name) return field def _get_errors(self): "Returns an ErrorDict for the data provided for the form" try: if self._errors is None: self.full_clean() return self._errors except AttributeError: raise RuntimeError('Camouflaged AttributeError from _get_errors, original error: \n %s' % unicode(traceback.format_exc())) errors = property(_get_errors) def is_valid(self): """ Returns True if the form has no errors. Otherwise, False. If errors are being ignored, returns False. """ # import ipdb; ipdb.set_trace() return self.is_bound and not bool(self.errors) def add_prefix(self, field_name): """ Returns the field name with a prefix appended, if this Form has a prefix set. Subclasses may wish to override. """ return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name def render(self, indent_level=0): self.content = [] # empty previous content (if render would be called moretimes, there would be multiple forms instead one ) self.add(self.layout_class(self)) return super(BaseForm, self).render(indent_level) def non_field_errors(self): """ Returns an ErrorList of errors that aren't associated with a particular field -- i.e., from Form.clean(). Returns an empty ErrorList if there are none. """ result = self.errors.get(NON_FIELD_ERRORS, None) if not result: result = self.errors[NON_FIELD_ERRORS] = self.error_class() return result def is_empty(self, exceptions=None): """ Returns True if this form has been bound and all fields that aren't listed in exceptions are empty. """ # TODO: This could probably use some optimization exceptions = exceptions or [] for name, field in self.fields.items(): if name in exceptions: continue # value_from_datadict() gets the data from the dictionary. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. # HACK: ['', ''] and [None, None] deal with SplitDateTimeWidget. This should be more robust. if field.value not in (None, '', ['', ''], [None, None]): return False return True def full_clean(self): """ Cleans all of self.data and populates self._errors and self.cleaned_data. """ self._errors = ErrorDict() if not self.is_bound: # Stop further processing. return self.cleaned_data = {} if self.empty_permitted and not self.has_changed(): self.cleaned_data = None return for name, field in self.fields.items(): self.clean_field(name, field) try: self.cleaned_data = self.clean() except ValidationError, e: self._errors[NON_FIELD_ERRORS] = e.messages if self._errors: delattr(self, 'cleaned_data')