def clean(self, value):
        """
        We clean every subwidget.
        """
        clean_data = []
        errors = ErrorList()
        is_empty = not value or not [v for v in value if v not in self.empty_values]
        if is_empty and not self.required:
            return []

        if is_empty and self.required:
            raise ValidationError(self.error_messages['required'])

        if value and not isinstance(value, (list, tuple)):
            raise ValidationError(self.error_messages['invalid'])

        for field_value, checkbox_value in value:
            try:
                clean_data.append([self.contained_field.clean(field_value), checkbox_value])
            except ValidationError as e:
                errors.extend(e.messages)
            # FIXME: copy paste from above
            if self.contained_field.required:
                self.contained_field.required = False
        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Beispiel #2
0
 def get_error_titles(self):
     errors = ErrorList()
     for form in self.formsets:
         for item in form.errors:
             if item:
                 errors.extend(item)
     return errors
Beispiel #3
0
    def clean(self, value):
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in self.empty_values]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return []
        else:
            raise ValidationError(self.error_messages['invalid'])
        
        for field_value in value:
            try:
                clean_data.append(self.contained_field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
            if self.contained_field.required:
                self.contained_field.required = False
        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Beispiel #4
0
 def errors(self):
     errors = ErrorList(self.form.errors)
     for inline_formset in self.inline_formsets.values():
         errors.extend(inline_formset.non_form_errors())
         for inline_formset_errors in inline_formset.errors:
             errors.extend(inline_formset_errors.values())
     return errors
Beispiel #5
0
	def get_error_titles(self):
		errors = ErrorList()
		for form in self.formsets:
			for item in form.errors:
				if item:
					errors.extend(item)
		return errors
Beispiel #6
0
    def clean(self, value):
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [
                    v for v in value if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return []
        else:
            raise ValidationError(self.error_messages['invalid'])

        for field_value in value:
            try:
                clean_data.append(self.contained_field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
            if self.contained_field.required:
                self.contained_field.required = False
        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Beispiel #7
0
    def clean(self, value):
        """
        Validates every value in the given list. A value is validated against
        the corresponding Field in self.fields.

        For example, if this MultiValueField was instantiated with
        fields=(DateField(), TimeField()), clean() would call
        DateField.clean(value[0]) and TimeField.clean(value[1]).
        """
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [
                    v for v in value if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'],
                                          code='required')
                else:
                    return self.compress([])
        else:
            raise ValidationError(self.error_messages['invalid'],
                                  code='invalid')
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            if field_value in self.empty_values:
                if self.require_all_fields:
                    # Raise a 'required' error if the MultiValueField is
                    # required and any field is empty.
                    if self.required:
                        raise ValidationError(self.error_messages['required'],
                                              code='required')
                elif field.required:
                    # Otherwise, add an 'incomplete' error to the list of
                    # collected errors and skip field cleaning, if a required
                    # field is empty.
                    if field.error_messages['incomplete'] not in errors:
                        errors.append(field.error_messages['incomplete'])
                    continue
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter. Skip duplicates.
                errors.extend(m for m in e.error_list if m not in errors)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
Beispiel #8
0
    def clean(self, value):
        """
        Validates every value in the given list. A value is validated against
        the corresponding Field in self.fields.

        For example, if this MultiValueField was instantiated with
        fields=(DateField(), TimeField()), clean() would call
        DateField.clean(value[0]) and TimeField.clean(value[1]).
        """
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in self.empty_values]:
                if self.required:
                    raise ValidationError(self.error_messages['required'], code='required')
                else:
                    return self.compress([])
        else:
            raise ValidationError(self.error_messages['invalid'], code='invalid')
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            if field_value in self.empty_values:
                if self.require_all_fields:
                    # Raise a 'required' error if the MultiValueField is
                    # required and any field is empty.
                    if self.required:
                        raise ValidationError(self.error_messages['required'], code='required')
                elif field.required:
                    # Otherwise, add an 'incomplete' error to the list of
                    # collected errors and skip field cleaning, if a required
                    # field is empty.
                    if field.error_messages['incomplete'] not in errors:
                        errors.append(field.error_messages['incomplete'])
                    continue
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter. Skip duplicates.
                errors.extend(m for m in e.error_list if m not in errors)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
Beispiel #9
0
 def post(self, request, *args, **kwargs):
     if self.async_response is not None:
         return self.async_response
     if self.subscription_form.is_valid():
         try:
             subscription = self.subscription_form.create_subscription()
             return HttpResponseRedirect(
                 reverse(EditSubscriptionView.urlname, args=(subscription.id,))
             )
         except NewSubscriptionError as e:
             errors = ErrorList()
             errors.extend([e.message])
             self.subscription_form._errors.setdefault(NON_FIELD_ERRORS, errors)
     return self.get(request, *args, **kwargs)
Beispiel #10
0
 def post(self, request, *args, **kwargs):
     if self.async_response is not None:
         return self.async_response
     if self.subscription_form.is_valid():
         try:
             subscription = self.subscription_form.create_subscription()
             return HttpResponseRedirect(
                 reverse(EditSubscriptionView.urlname, args=(subscription.id,))
             )
         except NewSubscriptionError as e:
             errors = ErrorList()
             errors.extend([str(e)])
             self.subscription_form._errors.setdefault(NON_FIELD_ERRORS, errors)
     return self.get(request, *args, **kwargs)
Beispiel #11
0
    def clean(self, value):
        clean_data = {}
        errors = ErrorList()
        if not value or isinstance(value, dict):
            if not value or not [
                    v for v in value.values() if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return {}
        else:
            raise ValidationError(self.error_messages['invalid'])

        # sort out required => at least one element must be in there
        for key, val in value.items():
            # ignore empties. Can they even come up here?
            if key in self.empty_values and val in self.empty_values:
                continue

            try:
                val = self.contained_field.clean(val)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            try:
                self._validate_key(key)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            clean_data[key] = val

            if self.contained_field.required:
                self.contained_field.required = False

        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Beispiel #12
0
    def clean(self, value):
        clean_data = {}
        errors = ErrorList()
        if not value or isinstance(value, dict):
            if not value or not [
                    v for v in value.values() if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return {}
        else:
            raise ValidationError(self.error_messages['invalid'])

        # sort out required => at least one element must be in there
        for key, val in value.items():
            # ignore empties. Can they even come up here?
            if key in self.empty_values and val in self.empty_values:
                continue

            try:
                val = self.contained_field.clean(val)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            try:
                self._validate_key(key)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            clean_data[key] = val

            if self.contained_field.required:
                self.contained_field.required = False

        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Beispiel #13
0
    def clean(self, value):
        """
        Validates every value in the given list. A value is validated against
        the corresponding Field in self.fields.

        Only allows for exactly 1 valid value to be submitted, this is what
        gets returned by compress.

        example to use directy (instead of using FileOrURLField):
            MutuallyExclusiveValueField(
                fields=(forms.TypedChoiceField(choices=[(1,1), (2,2)], coerce=int),
                        forms.IntegerField()))
        """
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [
                    v for v in value if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'],
                                          code='required')
                else:
                    return self.compress([])
        else:
            raise ValidationError(self.error_messages['invalid'],
                                  code='invalid')
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
    def clean(self, value):
        """
        This is a copy of MultiValueField.clean() with a BUGFIX:
        -   if self.required and field_value in validators.EMPTY_VALUES:
        +   if field.required and field_value in validators.EMPTY_VALUES:
        """
        try:
            from django.forms.utils import ErrorList
        except ImportError:
            from django.forms.util import ErrorList
        from django.core import validators
        from django.core.exceptions import ValidationError

        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in validators.EMPTY_VALUES]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return self.compress(value)
        else:
            raise ValidationError(self.error_messages['invalid'])
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            if field.required and field_value in validators.EMPTY_VALUES:
                raise ValidationError(self.error_messages['required'])
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
Beispiel #15
0
    def clean(self, value):
        # Get the value
        # Totally replaced validation.
        clean_data = []
        errors = ErrorList()

        # Only the visible field is required.
        radio_value = value[0]
        field_visible = [False] * len(self.fields)
        field_visible[0] = True
        if radio_value is None:
            # radio_value is None when models are deleted in formsets
            out = ''
        else:
            field_visible[self.url_type_registry.index(radio_value) + 1] = True

            # The validators only fire for visible fields.
            for i, field in enumerate(self.fields):
                try:
                    field_value = value[i]
                except IndexError:
                    field_value = None

                if not field_visible[i]:
                    clean_data.append(None)
                    continue

                if self.required and field_value in validators.EMPTY_VALUES:
                    raise ValidationError(self.error_messages['required'])

                try:
                    clean_data.append(field.clean(field_value))
                except ValidationError as e:
                    errors.extend(e.messages)  # Collect all widget errors
            if errors:
                raise ValidationError(errors)

            out = self.compress(clean_data)

        self.validate(out)
        return out
Beispiel #16
0
    def clean(self, value):
        # Get the value
        # Totally replaced validation.
        clean_data = []
        errors = ErrorList()

        # Only the visible field is required.
        radio_value = value[0]
        field_visible = [False] * len(self.fields)
        field_visible[0] = True
        if radio_value is None:
            # radio_value is None when models are deleted in formsets
            out = ''
        else:
            field_visible[self.url_type_registry.index(radio_value) + 1] = True

            # The validators only fire for visible fields.
            for i, field in enumerate(self.fields):
                try:
                    field_value = value[i]
                except IndexError:
                    field_value = None

                if not field_visible[i]:
                    clean_data.append(None)
                    continue

                if self.required and field_value in validators.EMPTY_VALUES:
                    raise ValidationError(self.error_messages['required'])

                try:
                    clean_data.append(field.clean(field_value))
                except ValidationError as e:
                    errors.extend(e.messages)  # Collect all widget errors
            if errors:
                raise ValidationError(errors)

            out = self.compress(clean_data)

        self.validate(out)
        return out
Beispiel #17
0
    def clean_sub_fields(self, value):
        """'value' being the list of the values of the subfields, validate
        each subfield."""
        clean_data = []
        errors = ErrorList()
        # Remove the field corresponding to the SKIP_CHECK_NAME boolean field
        # if required.
        fields = self.fields if not self.skip_check else self.fields[:-1]
        for index, field in enumerate(fields):
            try:
                field_value = value[index]
            except IndexError:
                field_value = None
            # Set the field_value to the default value if not set.
            if field_value is None and field.initial not in (None, ""):
                field_value = field.initial
            # Check the field's 'required' field instead of the global
            # 'required' field to allow subfields to be required or not.
            if field.required and field_value in validators.EMPTY_VALUES:
                errors.append("%s: %s" %
                              (field.label, self.error_messages["required"]))
                continue
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend("%s: %s" % (field.label, message)
                              for message in e.messages)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        return out
Beispiel #18
0
    def bulk_view(self, request, form_url='', extra_context=None):
        to_field = request.POST.get(TO_FIELD_VAR,
                                    request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField(
                "The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        continue_requested = request.POST.get('_continue',
                                              request.GET.get('_continue'))
        force_continue = False
        inline = self.get_bulk_inline(request)
        formset_class = inline.get_formset(request)
        formset_params = {}
        prefix = formset_class.get_default_prefix()
        queryset = inline.get_queryset(request)

        if not self.has_add_permission(request):
            formset_class.max_num = 0

        if request.method == 'GET':
            if 'pks' in request.GET and self.has_change_permission(request):
                pks = [
                    opts.pk.to_python(pk)
                    for pk in request.GET.get('pks').split(',')
                ]
                queryset = queryset.filter(pk__in=pks)
            else:
                queryset = queryset.none()

        elif request.method == 'POST':
            management_form = ManagementForm(request.POST, prefix=prefix)

            if not management_form.is_valid():
                raise ValidationError(
                    _('ManagementForm data is missing or has been tampered with'
                      ),
                    code='missing_management_form',
                )

            if not self.has_add_permission(
                    request) and management_form.cleaned_data[
                        INITIAL_FORM_COUNT] < management_form.cleaned_data[
                            TOTAL_FORM_COUNT]:
                raise PermissionDenied

            if not self.has_change_permission(
                    request
            ) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0:
                raise PermissionDenied

            queryset = self.transform_queryset(request, queryset,
                                               management_form, prefix)

            post, files, force_continue = self.transform_post_and_files(
                request, prefix)
            formset_params.update({
                'data': post,
                'files': files,
            })

        formset_params['queryset'] = queryset

        formset = formset_class(**formset_params)

        if request.method == 'POST':
            if formset.is_valid():
                self.save_formset(request,
                                  form=None,
                                  formset=formset,
                                  change=False)

                if continue_requested or force_continue:
                    # The implementation of ModelAdmin redirects to the change view if valid and continue was requested
                    # The change view then reads the edited model again from database
                    # In our case, we can't make a redirect as we would loose the information which models should be edited
                    # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request

                    if self.has_change_permission(request):
                        queryset = _ListQueryset(queryset)
                        queryset.extend(formset.new_objects)
                    else:
                        queryset = _ListQueryset()

                    formset_params.update({
                        'data': None,
                        'files': None,
                        'queryset': queryset,
                    })

                    formset = formset_class(**formset_params)

                    msg = _(
                        'The %s were bulk added successfully. You may edit them again below.'
                    ) % (force_text(opts.verbose_name_plural), )
                    self.message_user(request, msg, messages.SUCCESS)

                else:
                    return self.response_bulk(request, formset)

        media = self.media

        inline_formsets = self.get_inline_formsets(request, [formset],
                                                   [inline],
                                                   obj=None)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        errors = ErrorList()

        if formset.is_bound:
            errors.extend(formset.non_form_errors())
            for formset_errors in formset.errors:
                errors.extend(list(iter(formset_errors.values())))

        context = self.admin_site.each_context(request)
        context.update({
            'bulk':
            True,
            'bulk_formset_prefix':
            prefix,
            'bulk_upload_fields':
            self.get_bulk_upload_fields(request),
            'title':
            _('Bulk add %s') % force_text(opts.verbose_name_plural),
            'is_popup': (IS_POPUP_VAR in request.POST
                         or IS_POPUP_VAR in request.GET),
            'to_field':
            to_field,
            'media':
            media,
            'inline_admin_formsets':
            inline_formsets,
            'errors':
            errors,
            'preserved_filters':
            self.get_preserved_filters(request),
            'adminform':
            admin.helpers.AdminForm(ManagementForm(), [], {}),
        })
        context.update(extra_context or {})

        return self.render_change_form(request,
                                       context,
                                       add=True,
                                       change=False,
                                       obj=None,
                                       form_url=form_url)
Beispiel #19
0
	def get_error_list(self):
		errors = ErrorList()
		if self.form_obj.is_bound:
			errors.extend(self.form_obj.errors.values())
		return errors
Beispiel #20
0
 def get_error_list(self):
     errors = ErrorList()
     if self.form_obj.is_bound:
         errors.extend(self.form_obj.errors.values())
     return errors
def hidden_field_errors(form):
    hidden_field_errors = ErrorList()
    for field in form.hidden_fields():
        hidden_field_errors.extend(field.errors)
    return hidden_field_errors
def hidden_field_errors(form):
    hidden_field_errors = ErrorList()
    for field in form.hidden_fields():
        hidden_field_errors.extend(field.errors)
    return hidden_field_errors
Beispiel #23
0
    def bulk_view(self, request, form_url='', extra_context=None):
        to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        continue_requested = request.POST.get('_continue', request.GET.get('_continue'))
        force_continue = False
        inline = self.get_bulk_inline(request)
        formset_class = inline.get_formset(request)
        formset_params = {}
        prefix = formset_class.get_default_prefix()
        queryset = inline.get_queryset(request)

        if not self.has_add_permission(request):
            formset_class.max_num = 0

        if request.method == 'GET':
            if 'pks' in request.GET and self.has_change_permission(request):
                pks = [opts.pk.to_python(pk) for pk in request.GET.get('pks').split(',')]
                queryset = queryset.filter(pk__in=pks)
            else:
                queryset = queryset.none()

        elif request.method == 'POST':
            management_form = ManagementForm(request.POST, prefix=prefix)

            if not management_form.is_valid():
                raise ValidationError(
                    _('ManagementForm data is missing or has been tampered with'),
                    code='missing_management_form',
                )

            if not self.has_add_permission(request) and management_form.cleaned_data[INITIAL_FORM_COUNT] < management_form.cleaned_data[TOTAL_FORM_COUNT]:
                raise PermissionDenied

            if not self.has_change_permission(request) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0:
                raise PermissionDenied

            queryset = self.transform_queryset(request, queryset, management_form, prefix)

            post, files, force_continue = self.transform_post_and_files(request, prefix)
            formset_params.update({
                'data': post,
                'files': files,
            })

        formset_params['queryset'] = queryset

        formset = formset_class(**formset_params)

        if request.method == 'POST':
            if formset.is_valid():
                self.save_formset(request, form=None, formset=formset, change=False)

                if continue_requested or force_continue:
                    # The implementation of ModelAdmin redirects to the change view if valid and continue was requested
                    # The change view then reads the edited model again from database
                    # In our case, we can't make a redirect as we would loose the information which models should be edited
                    # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request

                    if self.has_change_permission(request):
                        queryset = _ListQueryset(queryset)
                        queryset.extend(formset.new_objects)
                    else:
                        queryset = _ListQueryset()

                    formset_params.update({
                        'data': None,
                        'files': None,
                        'queryset': queryset,
                    })

                    formset = formset_class(**formset_params)

                    msg = _('The %s were bulk added successfully. You may edit them again below.') % (force_text(opts.verbose_name_plural),)
                    self.message_user(request, msg, messages.SUCCESS)

                else:
                    return self.response_bulk(request, formset)

        media = self.media

        inline_formsets = self.get_inline_formsets(request, [formset], [inline], obj=None)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        errors = ErrorList()

        if formset.is_bound:
            errors.extend(formset.non_form_errors())
            for formset_errors in formset.errors:
                errors.extend(list(six.itervalues(formset_errors)))

        context = dict(
            self.admin_site.each_context(request) if django.VERSION >= (1, 8) else self.admin_site.each_context(),
            bulk=True,
            bulk_formset_prefix=prefix,
            bulk_upload_fields=self.get_bulk_upload_fields(request),
            title=_('Bulk add %s') % force_text(opts.verbose_name_plural),
            is_popup=(IS_POPUP_VAR in request.POST or
                      IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=errors,
            preserved_filters=self.get_preserved_filters(request),
        )

        context.update(extra_context or {})

        return self.render_change_form(request, context, add=True, change=False, obj=None, form_url=form_url)
Beispiel #24
0
    def bulk_view(self, request, form_url='', extra_context=None):
        to_field = request.POST.get(TO_FIELD_VAR,
                                    request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField(
                "The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        continue_requested = request.POST.get('_continue',
                                              request.GET.get('_continue'))
        force_continue = False
        inline = self.get_bulk_inline(request)
        formset_class = inline.get_formset(request)
        formset_params = {}
        prefix = formset_class.get_default_prefix()
        queryset = inline.get_queryset(request)

        if not self.has_add_permission(request):
            formset_class.max_num = 0

        if request.method == 'GET':
            if 'pks' in request.GET and self.has_change_permission(request):
                pks = [
                    opts.pk.to_python(pk)
                    for pk in request.GET.get('pks').split(',')
                ]
                queryset = queryset.filter(pk__in=pks)
            else:
                queryset = queryset.none()

        elif request.method == 'POST':
            management_form = ManagementForm(request.POST, prefix=prefix)

            if not management_form.is_valid():
                raise ValidationError(
                    _('ManagementForm data is missing or has been tampered with'
                      ),
                    code='missing_management_form',
                )

            if not self.has_add_permission(
                    request) and management_form.cleaned_data[
                        INITIAL_FORM_COUNT] < management_form.cleaned_data[
                            TOTAL_FORM_COUNT]:
                raise PermissionDenied

            if not self.has_change_permission(
                    request
            ) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0:
                raise PermissionDenied

            queryset = self.transform_queryset(request, queryset,
                                               management_form, prefix)

            post, files, force_continue = self.transform_post_and_files(
                request, prefix)
            formset_params.update({
                'data': post,
                'files': files,
            })

        formset_params['queryset'] = queryset

        formset = formset_class(**formset_params)

        if request.method == 'POST':
            if formset.is_valid():
                self.save_formset(request,
                                  form=None,
                                  formset=formset,
                                  change=False)

                if continue_requested or force_continue:
                    # The implementation of ModelAdmin redirects to the change view if valid and continue was requested
                    # The change view then reads the edited model again from database
                    # In our case, we can't make a redirect as we would loose the information which models should be edited
                    # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request

                    if self.has_change_permission(request):
                        queryset = _ListQueryset(queryset)
                        queryset.extend(formset.new_objects)
                    else:
                        queryset = _ListQueryset()

                    formset_params.update({
                        'data': None,
                        'files': None,
                        'queryset': queryset,
                    })

                    formset = formset_class(**formset_params)

                    msg = _(
                        'The %s were bulk added successfully. You may edit them again below.'
                    ) % (force_text(opts.verbose_name_plural), )
                    self.message_user(request, msg, messages.SUCCESS)

                else:
                    return self.response_bulk(request, formset)

        media = self.media

        inline_formsets = self.get_inline_formsets(request, [formset],
                                                   [inline],
                                                   obj=None)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        errors = ErrorList()

        if formset.is_bound:
            errors.extend(formset.non_form_errors())
            for formset_errors in formset.errors:
                errors.extend(list(six.itervalues(formset_errors)))

        print("type(inline_formsets)")
        print(type(inline_formsets))
        print(inline_formsets)
        print(*inline_formsets, sep=", ")
        print("request")
        print(type(request))
        print(request)
        context = dict(
            self.admin_site.each_context(request) if django.VERSION >=
            (1, 8) else self.admin_site.each_context(),
            bulk=True,
            bulk_formset_prefix=prefix,
            bulk_upload_fields=self.get_bulk_upload_fields(request),
            title=_('Bulk add %s') % force_text(opts.verbose_name_plural),
            is_popup=(IS_POPUP_VAR in request.POST
                      or IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=errors,
            preserved_filters=self.get_preserved_filters(request),
            # adminform=inline_formsets,
            # adminform=super(BulkModelAdmin, self).get_form(request, **kwargs) #kwargs not define
            # adminform=super(BulkModelAdmin, self).get_form(request) #object 'ContainerForm' has no attribute 'form'
            # searching for ContainerForm gives me nothing
            #writing a dummy form - uses models
            # adminform=DummyModelForm
            # but that ModelForm has no modelclass, nothing in models.py
        )

        context.update(extra_context or {})

        # print(context)

        return self.render_change_form(request,
                                       context,
                                       add=True,
                                       change=False,
                                       obj=None,
                                       form_url=form_url)