# Path: djng/forms/angular_base.py
# class NgFormBaseMixin(object):
#     form_error_css_classes = 'djng-form-errors'
#     field_error_css_classes = 'djng-field-errors'
# 
#     def __init__(self, *args, **kwargs):
#         try:
#             form_name = self.form_name
#         except AttributeError:
#             # if form_name is unset, generate a pseudo unique name, based upon the class name
#             form_name = b64encode(self.__class__.__name__.encode()).rstrip(b'=').decode('utf-8')
#         self.form_name = kwargs.pop('form_name', form_name)
#         error_class = kwargs.pop('error_class', TupleErrorList)
#         kwargs.setdefault('error_class', error_class)
#         super(NgFormBaseMixin, self).__init__(*args, **kwargs)
#         if isinstance(self.data, QueryDict):
#             self.data = self.rectify_multipart_form_data(self.data.copy())
#         elif isinstance(self.data, dict) and self.data:
#             self.data = self.rectify_ajax_form_data(self.data.copy())
# 
#     def __getitem__(self, name):
#         "Returns a NgBoundField with the given name."
#         try:
#             field = self.fields[name]
#         except KeyError:
#             raise KeyError('Key %r not found in Form' % name)
#         return NgBoundField(self, field, name)
# 
#     def add_prefix(self, field_name):
#         """
#         Rewrite the model keys to use dots instead of dashes, since thats the syntax
#         used in Angular models.
#         """
#         return ('%s.%s' % (self.prefix, field_name)) if self.prefix else field_name
# 
#     def get_field_errors(self, field):
#         """
#         Return server side errors. Shall be overridden by derived forms to add their
#         extra errors for AngularJS.
#         """
#         identifier = format_html('{0}[\'{1}\']', self.form_name, field.name)
#         errors = self.errors.get(field.html_name, [])
#         return self.error_class([SafeTuple(
#             (identifier, self.field_error_css_classes, '$pristine', '$pristine', 'invalid', e)) for e in errors])
# 
#     def non_field_errors(self):
#         # See TupleErrorList.extend for an explanation
#         hidden_field_errors = []
#         for name, field in self.fields.items():
#             bf = self[name]
#             bf_errors = [conditional_escape(error) for error in bf.errors]
#             if bf.is_hidden and bf_errors:
#                 hidden_field_errors += [SafeTuple(
#                     (self.form_name, self.form_error_css_classes, '$pristine', '{}.$isEmpty()'.format(name), 'invalid',
#                         '(Hidden field {}) {}'.format(name, e[5])) ) for e in bf_errors]
#         errors = super(NgFormBaseMixin, self).non_field_errors()
#         return self.error_class(hidden_field_errors + [SafeTuple(
#             (self.form_name, self.form_error_css_classes, '$pristine', '$pristine', 'invalid', e)) for e in errors])
# 
#     def update_widget_attrs(self, bound_field, attrs):
#         """
#         Updated the widget attributes which shall be added to the widget when rendering this field.
#         """
#         if bound_field.field.has_subwidgets() is False:
#             widget_classes = getattr(self, 'widget_css_classes', None)
#             if widget_classes:
#                 if 'class' in attrs:
#                     attrs['class'] += ' ' + widget_classes
#                 else:
#                     attrs.update({'class': widget_classes})
#         return attrs
# 
#     def rectify_multipart_form_data(self, data):
#         """
#         If a widget was converted and the Form data was submitted through a multipart request,
#         then these data fields must be converted to suit the Django Form validation
#         """
#         for name, field in self.base_fields.items():
#             try:
#                 field.implode_multi_values(name, data)
#             except AttributeError:
#                 pass
#         return data
# 
#     def rectify_ajax_form_data(self, data):
#         """
#         If a widget was converted and the Form data was submitted through an Ajax request,
#         then these data fields must be converted to suit the Django Form validation
#         """
#         for name, field in self.base_fields.items():
#             try:
#                 data[name] = field.convert_ajax_data(data.get(name, {}))
#             except AttributeError:
#                 pass
#         return data
# 
# class SafeTuple(SafeData, tuple):
#     """
#     Used to bypass escaping of TupleErrorList by the ``conditional_escape`` function in Django's
#     form rendering.
#     """


from django.forms.utils import ErrorDict
from django.utils.html import format_html
from djng.forms.angular_base import NgFormBaseMixin, SafeTuple
        """
        Rewrite the error dictionary, so that its keys correspond to the model fields.
        """
        super(NgModelFormMixin, self)._post_clean()
        if self._errors and self.prefix:
            self._errors = ErrorDict((self.add_prefix(name), value) for name, value in self._errors.items())

    def get_initial_data(self):
        """
        Return a dictionary specifying the defaults for this form. This dictionary can be used to
        inject the initial values for an Angular controller using the directive:
        ``ng-init={{ thisform.get_initial_data|js|safe }}``.
        """
        data = {}
        ng_models = hasattr(self, 'Meta') and getattr(self.Meta, 'ng_models', []) or []
        for name, field in self.fields.items():
            if 'ng-model' in self.ng_directives or name in ng_models:
                data[name] = self.initial.get(name) if self.initial else field.initial
        return data

    def get_field_errors(self, field):
        errors = super(NgModelFormMixin, self).get_field_errors(field)
        if field.is_hidden:
            return errors
        identifier = format_html('{0}[\'{1}\']', self.form_name, field.html_name)
        errors.append(SafeTuple((identifier, self.field_error_css_classes, '$pristine', '$error.rejected', 'invalid', '$message')))
        return errors

    def non_field_errors(self):
        errors = super(NgModelFormMixin, self).non_field_errors()

# Path: djng/forms/angular_base.py
# class NgFormBaseMixin(object):
#     form_error_css_classes = 'djng-form-errors'
#     field_error_css_classes = 'djng-field-errors'
# 
#     def __init__(self, *args, **kwargs):
#         try:
#             form_name = self.form_name
#         except AttributeError:
#             # if form_name is unset, generate a pseudo unique name, based upon the class name
#             form_name = b64encode(self.__class__.__name__.encode()).rstrip(b'=').decode('utf-8')
#         self.form_name = kwargs.pop('form_name', form_name)
#         error_class = kwargs.pop('error_class', TupleErrorList)
#         kwargs.setdefault('error_class', error_class)
#         super(NgFormBaseMixin, self).__init__(*args, **kwargs)
#         if isinstance(self.data, QueryDict):
#             self.data = self.rectify_multipart_form_data(self.data.copy())
#         elif isinstance(self.data, dict) and self.data:
#             self.data = self.rectify_ajax_form_data(self.data.copy())
# 
#     def __getitem__(self, name):
#         "Returns a NgBoundField with the given name."
#         try:
#             field = self.fields[name]
#         except KeyError:
#             raise KeyError('Key %r not found in Form' % name)
#         return NgBoundField(self, field, name)
# 
#     def add_prefix(self, field_name):
#         """
#         Rewrite the model keys to use dots instead of dashes, since thats the syntax
#         used in Angular models.
#         """
#         return ('%s.%s' % (self.prefix, field_name)) if self.prefix else field_name
# 
#     def get_field_errors(self, field):
#         """
#         Return server side errors. Shall be overridden by derived forms to add their
#         extra errors for AngularJS.
#         """
#         identifier = format_html('{0}[\'{1}\']', self.form_name, field.name)
#         errors = self.errors.get(field.html_name, [])
#         return self.error_class([SafeTuple(
#             (identifier, self.field_error_css_classes, '$pristine', '$pristine', 'invalid', e)) for e in errors])
# 
#     def non_field_errors(self):
#         # See TupleErrorList.extend for an explanation
#         hidden_field_errors = []
#         for name, field in self.fields.items():
#             bf = self[name]
#             bf_errors = [conditional_escape(error) for error in bf.errors]
#             if bf.is_hidden and bf_errors:
#                 hidden_field_errors += [SafeTuple(
#                     (self.form_name, self.form_error_css_classes, '$pristine', '{}.$isEmpty()'.format(name), 'invalid',
#                         '(Hidden field {}) {}'.format(name, e[5])) ) for e in bf_errors]
#         errors = super(NgFormBaseMixin, self).non_field_errors()
#         return self.error_class(hidden_field_errors + [SafeTuple(
#             (self.form_name, self.form_error_css_classes, '$pristine', '$pristine', 'invalid', e)) for e in errors])
# 
#     def update_widget_attrs(self, bound_field, attrs):
#         """
#         Updated the widget attributes which shall be added to the widget when rendering this field.
#         """
#         if bound_field.field.has_subwidgets() is False:
#             widget_classes = getattr(self, 'widget_css_classes', None)
#             if widget_classes:
#                 if 'class' in attrs:
#                     attrs['class'] += ' ' + widget_classes
#                 else:
#                     attrs.update({'class': widget_classes})
#         return attrs
# 
#     def rectify_multipart_form_data(self, data):
#         """
#         If a widget was converted and the Form data was submitted through a multipart request,
#         then these data fields must be converted to suit the Django Form validation
#         """
#         for name, field in self.base_fields.items():
#             try:
#                 field.implode_multi_values(name, data)
#             except AttributeError:
#                 pass
#         return data
# 
#     def rectify_ajax_form_data(self, data):
#         """
#         If a widget was converted and the Form data was submitted through an Ajax request,
#         then these data fields must be converted to suit the Django Form validation
#         """
#         for name, field in self.base_fields.items():
#             try:
#                 data[name] = field.convert_ajax_data(data.get(name, {}))
#             except AttributeError:
#                 pass
#         return data
# 
# class SafeTuple(SafeData, tuple):
#     """
#     Used to bypass escaping of TupleErrorList by the ``conditional_escape`` function in Django's
#     form rendering.
#     """


# Path: djng/forms/angular_model.py
from django.forms.utils import ErrorDict
from django.utils.html import format_html
from djng.forms.angular_base import NgFormBaseMixin, SafeTuple

        """
        Rewrite the error dictionary, so that its keys correspond to the model fields.
        """
        super(NgModelFormMixin, self)._post_clean()
        if self._errors and self.prefix:
            self._errors = ErrorDict((self.add_prefix(name), value) for name, value in self._errors.items())

    def get_initial_data(self):
        """
        Return a dictionary specifying the defaults for this form. This dictionary can be used to
        inject the initial values for an Angular controller using the directive:
        ``ng-init={{ thisform.get_initial_data|js|safe }}``.
        """
        data = {}
        ng_models = hasattr(self, 'Meta') and getattr(self.Meta, 'ng_models', []) or []
        for name, field in self.fields.items():
            if 'ng-model' in self.ng_directives or name in ng_models:
                data[name] = self.initial.get(name) if self.initial else field.initial
        return data

    def get_field_errors(self, field):
        errors = super(NgModelFormMixin, self).get_field_errors(field)
        if field.is_hidden:
            return errors
        identifier = format_html('{0}[\'{1}\']', self.form_name, field.html_name)
        errors.append(SafeTuple((identifier, self.field_error_css_classes, '$pristine', '$error.rejected', 'invalid', '$message')))
        return errors

    def non_field_errors(self):
        errors = super(NgModelFormMixin, self).non_field_errors()

        errors.append(SafeTuple((self.form_name, self.form_error_css_classes, '$pristine', '$error.rejected', 'invalid', '$message')))