Пример #1
0
    def get_model_form(self, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "fields": self.fields and list(self.fields) or None,
            "exclude": exclude,
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        return modelform_factory(self.model, **defaults)
Пример #2
0
    def get_model_form(self, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields())
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "fields": self.fields and list(self.fields) or None,
            "exclude": exclude,
            "formfield_callback": self.formfield_for_dbfield,
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        # return modelform_factory(self.model, **defaults)
        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
                             % (e, self.__class__.__name__))
Пример #3
0
    def get_model_form(self, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields())
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "fields": self.fields and list(self.fields) or None,
            "exclude": exclude,
            "formfield_callback": self.formfield_for_dbfield,
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        return modelform_factory(self.model, **defaults)

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
                             % (e, self.__class__.__name__))
Пример #4
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(request, obj)
        defaults = {
            "ct_field": self.ct_field,
            "fk_field": self.ct_fk_field,
            "form": self.form,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "formset": self.formset,
            "extra": self.extra,
            "can_delete": can_delete,
            "can_order": False,
            "fields": fields,
            "max_num": self.max_num,
            "exclude": exclude
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = ALL_FIELDS

        return generic_inlineformset_factory(self.model, **defaults)
Пример #5
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        exclude = [*(self.exclude or []), *self.get_readonly_fields(request, obj)]
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(request, obj)
        defaults = {
            'ct_field': self.ct_field,
            'fk_field': self.ct_fk_field,
            'form': self.form,
            'formfield_callback': partial(self.formfield_for_dbfield, request=request),
            'formset': self.formset,
            'extra': self.get_extra(request, obj),
            'can_delete': can_delete,
            'can_order': False,
            'fields': fields,
            'min_num': self.get_min_num(request, obj),
            'max_num': self.get_max_num(request, obj),
            'exclude': exclude,
            **kwargs,
        }

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = ALL_FIELDS

        return generic_inlineformset_factory(self.model, **defaults)
Пример #6
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        exclude = [*(self.exclude or []), *self.get_readonly_fields(request, obj)]
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(request, obj)
        defaults = {
            'ct_field': self.ct_field,
            'fk_field': self.ct_fk_field,
            'form': self.form,
            'formfield_callback': partial(self.formfield_for_dbfield, request=request),
            'formset': self.formset,
            'extra': self.get_extra(request, obj),
            'can_delete': can_delete,
            'can_order': False,
            'fields': fields,
            'min_num': self.get_min_num(request, obj),
            'max_num': self.get_max_num(request, obj),
            'exclude': exclude,
            **kwargs,
        }

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = ALL_FIELDS

        return generic_inlineformset_factory(self.model, **defaults)
Пример #7
0
    def get_formset(self, request, obj=None, **kwargs):
        if self.declared_fieldsets:
            fields = flatten_fieldsets(self.declared_fieldsets)
        else:
            fields = None
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(self.form, "_meta") and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(request, obj)
        defaults = {
            "ct_field": self.ct_field,
            "fk_field": self.ct_fk_field,
            "form": self.form,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "formset": self.formset,
            "extra": self.extra,
            "can_delete": can_delete,
            "can_order": False,
            "fields": fields,
            "max_num": self.max_num,
            "exclude": exclude,
        }
        defaults.update(kwargs)

        if defaults["fields"] is None and not modelform_defines_fields(defaults["form"]):
            defaults["fields"] = ALL_FIELDS

        return generic_inlineformset_factory(self.model, **defaults)
Пример #8
0
    def _get_form_factory_opts(self, request, obj=None, **kwargs):
        fieldsets = self.get_fieldsets(request, obj)
        if fieldsets:
            fields = flatten_fieldsets(fieldsets)
        else:
            fields = None
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)

        # construct the form_opts from declared_fieldsets
        form_opts = self.app_form_opts.copy()
        if fields is not None:
            # put app_name prefixed fields into form_opts
            for f in fields:
                if '.' not in f:
                    continue
                label, name = f.split('.')
                app_fields = form_opts.setdefault(label, {}).setdefault('fields', [])
                if name not in app_fields:
                    app_fields.append(name)
            # .. and remove them from fields for the model form
            fields = [f for f in fields if '.' not in f]

        # do the same for exclude
        for f in exclude:
            if '.' not in f:
                continue
            label, name = f.split('.')
            app_fields = form_opts.setdefault(label, {}).setdefault('exclude', [])
            if name not in app_fields:
                app_fields.append(name)
        exclude = [f for f in exclude if '.' not in f]

        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "multiform": self.multiform,
            "form_opts": form_opts,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)

        if hasattr(forms, 'ALL_FIELDS'):
            # Django 1.7
            if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
                defaults['fields'] = forms.ALL_FIELDS

        return defaults
Пример #9
0
    def get_form(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))

        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        readonly_fields = self.get_readonly_fields(request, obj)
        exclude.extend(readonly_fields)
        if excluded is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistent with the
        # default on modelform_factory
        exclude = exclude or None

        new_attrs = OrderedDict(
            (f, None) for f in readonly_fields
            if f in self.form.declared_fields
        )
        form = type(self.form.__name__, (self.form,), new_attrs)

        try:
            model = obj.content_type.model_class()
            model_key = model._meta.pk.name
        except (AttributeError, ObjectDoesNotExist):
            model = self.model.content_type.field.formfield().choices.queryset[0].model_class()
            model_key = 'id'

        defaults = {
            "form": form,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "widgets": {
                'content_type': ContentTypeSelect,
                'object_id': ForeignKeyRawIdWidget(
                    rel=ManyToOneRel(model_key, model, 'id'),
                    admin_site=admin.site
                )
            }
        }
        defaults.update(kwargs)
        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.'
                % (e, self.__class__.__name__)
            )
Пример #10
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))

        exclude = [
            *(self.exclude or []), *self.get_readonly_fields(request, obj)
        ]
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None

        can_delete = self.can_delete and self.has_delete_permission(
            request, obj)

        queryset = self.model.objects.none()
        if obj:
            queryset = self.get_form_queryset(obj)

        defaults = {
            'form':
            self.form,
            'formfield_callback':
            partial(self.formfield_for_dbfield, request=request),
            'formset':
            self.formset,
            'extra':
            self.get_extra(request, obj),
            'can_delete':
            can_delete,
            'can_order':
            False,
            'fields':
            fields,
            'min_num':
            self.get_min_num(request, obj),
            'max_num':
            self.get_max_num(request, obj),
            'exclude':
            exclude,
            'queryset':
            queryset,
            **kwargs,
        }

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = ALL_FIELDS

        return nonrelated_inlineformset_factory(
            self.model, save_new_instance=self.save_new_instance, **defaults)
Пример #11
0
    def get_changelist_form(self, request, **kwargs):
        """
        Returns a Form class for use in the Formset on the changelist page.
        """
        defaults = {
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)
        if defaults.get('fields') is None and not modelform_defines_fields(defaults.get('form')):
            defaults['fields'] = forms.ALL_FIELDS

        return documentform_factory(self.model, **defaults)
Пример #12
0
    def get_changelist_form(self, request, **kwargs):
        """
        Returns a Form class for use in the Formset on the changelist page.
        """
        defaults = {
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)
        if defaults.get('fields') is None and not modelform_defines_fields(defaults.get('form')):
            defaults['fields'] = forms.ALL_FIELDS

        return documentform_factory(self.model, **defaults)
Пример #13
0
    def get_formset(self, request, obj=None, **kwargs):
        if "fields" in kwargs:
            fields = kwargs.pop("fields")
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        exclude = [
            *(self.exclude or []), *self.get_readonly_fields(request, obj)
        ]
        if (self.exclude is None and hasattr(self.form, "_meta")
                and self.form._meta.exclude):
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(
            request, obj)
        defaults = {
            "ct_field":
            self.ct_field,
            "fk_field":
            self.ct_fk_field,
            "form":
            self.form,
            "formfield_callback":
            partial(self.formfield_for_dbfield, request=request),
            "formset":
            self.formset,
            "extra":
            self.get_extra(request, obj),
            "can_delete":
            can_delete,
            "can_order":
            False,
            "fields":
            fields,
            "min_num":
            self.get_min_num(request, obj),
            "max_num":
            self.get_max_num(request, obj),
            "exclude":
            exclude,
            **kwargs,
        }

        if defaults["fields"] is None and not modelform_defines_fields(
                defaults["form"]):
            defaults["fields"] = ALL_FIELDS

        return generic_inlineformset_factory(self.model, **defaults)
Пример #14
0
    def get_form(self, request, obj=None, **kwargs):
        if MODELADMIN_GET_EXCLUDE_SUPPORT:
            return super().get_form(request, obj, **kwargs)

        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        readonly_fields = self.get_readonly_fields(request, obj)
        exclude.extend(readonly_fields)

        if excluded is None and hasattr(self.form,
                                        '_meta') and self.form._meta.exclude:
            exclude.extend(self.form._meta.exclude)

        exclude = exclude or None

        new_attrs = OrderedDict((f, None) for f in readonly_fields
                                if f in self.form.declared_fields)

        form = type(self.form.__name__, (self.form, ), new_attrs)

        defaults = {
            "form":
            form,
            "fields":
            fields,
            "exclude":
            exclude,
            "formfield_callback":
            partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = ALL_FIELDS

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.' %
                (e, self.__class__.__name__))
    def get_form(self, request, obj=None, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistent with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form":
            self.form,
            "fields":
            fields,
            "exclude":
            exclude,
            "formfield_callback":
            partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = None

        print(defaults)
        try:
            return documentform_factory(self.model, **defaults)
        except FieldError as e:
            print(e.message)
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.' %
                (e, self.__class__.__name__))
Пример #16
0
 def get_changelist_form(self, request, **kwargs):
     """
     Return a Form class for use in the Formset on the changelist page.
     """
     # BEGIN CUSTOMIZATION
     defaults = {
         "formfield_callback":
         partial(
             # Override formfield_callback so checkboxes render correctly
             self.changelist_formfield_for_dbfield,
             request=request,
         ),
         **kwargs,
     }
     # END CUSTOMIZATION
     if defaults.get("fields") is None and not modelform_defines_fields(
             defaults.get("form")):
         defaults["fields"] = forms.ALL_FIELDS
     return modelform_factory(self.model, **defaults)
Пример #17
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if (self.exclude is None
                and hasattr(self.form, '_meta')
                and self.form._meta.exclude):
            # Take the custom ModelForm's Meta.exclude into account only if the
            # GenericInlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None
        can_delete = (self.can_delete
                      and self.has_delete_permission(request, obj))
        defaults = {
            "model_field": self.model_field,
            "parent_model_field": self.parent_model_field,
            "form": self.form,
            "formfield_callback": partial(self.formfield_for_dbfield,
                                          request=request),
            "formset": self.formset,
            "extra": self.get_extra(request, obj),
            "can_delete": can_delete,
            "can_order": False,
            "fields": fields,
            "min_num": self.get_min_num(request, obj),
            "max_num": self.get_max_num(request, obj),
            "exclude": exclude
        }
        defaults.update(kwargs)

        if (defaults['fields'] is None
                and not modelform_defines_fields(defaults['form'])):
            defaults['fields'] = ALL_FIELDS

        return arbitrary_inlineformset_factory(self.model,
                                               self.parent_model,
                                               **defaults)
Пример #18
0
    def get_form(self, request, obj=None, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistent with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = None

        print(defaults)
        try:
            return documentform_factory(self.model, **defaults)
        except FieldError as e:
            print(e.message)
            raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
                             % (e, self.__class__.__name__))
Пример #19
0
    def get_model_form(self, **kwargs):
        """
        根据 Model 返回 Form 类,用来显示表单。
        """
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields())
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            # 如果 :attr:`~xadmin.views.base.ModelAdminView.exclude` 是 None,并且 form 的 Meta.exclude 不为空,
            # 则使用 form 的 Meta.exclude
            exclude.extend(self.form._meta.exclude)
        # 如果 exclude 是空列表,那么就设为 None
        exclude = exclude or None
        defaults = {
            "form": self.form,
            "fields": self.fields and list(self.fields) or None,
            "exclude": exclude,
            "formfield_callback": self.formfield_for_dbfield,  # 设置生成表单字段的回调函数
        }
        defaults.update(kwargs)

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        return modelform_factory(self.model, **defaults)

        try:
            # 使用 modelform_factory 生成 Form 类
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.' %
                (e, self.__class__.__name__))
Пример #20
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # InlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # If exclude is an empty list we use None, since that's the actual
        # default.
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(
            request, obj)
        defaults = {
            "form":
            self.form,
            "formset":
            self.formset,
            "fields":
            fields,
            "exclude":
            exclude,
            "formfield_callback":
            partial(self.formfield_for_dbfield, request=request),
            "extra":
            self.get_extra(request, obj, **kwargs),
            "min_num":
            self.get_min_num(request, obj, **kwargs),
            "max_num":
            self.get_max_num(request, obj, **kwargs),
            "can_delete":
            can_delete,
        }

        defaults.update(kwargs)
        base_model_form = defaults['form']

        class DeleteProtectedModelForm(base_model_form):
            def hand_clean_DELETE(self):
                """
                We don't validate the 'DELETE' field itself because on
                templates it's not rendered using the field information, but
                just using a generic "deletion_field" of the InlineModelAdmin.
                """
                if self.cleaned_data.get(DELETION_FIELD_NAME, False):
                    using = router.db_for_write(self._meta.model)
                    collector = NestedObjects(using=using)
                    if self.instance.pk is None:
                        return
                    collector.collect([self.instance])
                    if collector.protected:
                        objs = []
                        for p in collector.protected:
                            objs.append(
                                # Translators: Model verbose name and instance representation,
                                # suitable to be an item in a list.
                                _('%(class_name)s %(instance)s') % {
                                    'class_name': p._meta.verbose_name,
                                    'instance': p
                                })
                        params = {
                            'class_name': self._meta.model._meta.verbose_name,
                            'instance': self.instance,
                            'related_objects': get_text_list(objs, _('and'))
                        }
                        msg = _(
                            "Deleting %(class_name)s %(instance)s would require "
                            "deleting the following protected related objects: "
                            "%(related_objects)s")
                        raise ValidationError(msg,
                                              code='deleting_protected',
                                              params=params)

            def is_valid(self):
                result = super(DeleteProtectedModelForm, self).is_valid()
                self.hand_clean_DELETE()
                return result

        defaults['form'] = DeleteProtectedModelForm

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        return modelformset_factory(self.model, **defaults)
Пример #21
0
    def get_formset(self, request, obj=None, **kwargs):  # noqa: C901
        """
        Copied from the Django InlineModelAdmin but instead of the inlineformset_factory we use the
        non_related_inlineformset_factory.
        """
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))

        exclude = [*(self.exclude or []), *self.get_readonly_fields(request, obj)]
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None

        can_delete = self.can_delete and self.has_delete_permission(request, obj)

        queryset = self.model.objects.none()
        if obj:
            queryset = self.get_form_queryset(obj)

        defaults = {
            'form': self.form,
            'formfield_callback': partial(self.formfield_for_dbfield, request=request),
            'formset': self.formset,
            'extra': self.get_extra(request, obj),
            'can_delete': can_delete,
            'can_order': False,
            'fields': fields,
            'min_num': self.get_min_num(request, obj),
            'max_num': self.get_max_num(request, obj),
            'exclude': exclude,
            'queryset': queryset,
            **kwargs,
        }

        base_model_form = defaults['form']
        can_change = self.has_change_permission(request, obj) if request else True
        can_add = self.has_add_permission(request, obj) if request else True

        class DeleteProtectedModelForm(base_model_form):

            def hand_clean_DELETE(self):
                """
                We don't validate the 'DELETE' field itself because on
                templates it's not rendered using the field information, but
                just using a generic "deletion_field" of the InlineModelAdmin.
                """
                if self.cleaned_data.get(DELETION_FIELD_NAME, False):
                    using = router.db_for_write(self._meta.model)
                    collector = NestedObjects(using=using)
                    if self.instance._state.adding:
                        return
                    collector.collect([self.instance])
                    if collector.protected:
                        objs = []
                        for p in collector.protected:
                            objs.append(
                                # Translators: Model verbose name and instance representation,
                                # suitable to be an item in a list.
                                _('%(class_name)s %(instance)s') % {
                                    'class_name': p._meta.verbose_name,
                                    'instance': p}
                            )
                        params = {
                            'class_name': self._meta.model._meta.verbose_name,
                            'instance': self.instance,
                            'related_objects': get_text_list(objs, _('and')),
                        }
                        msg = _("Deleting %(class_name)s %(instance)s would require "
                                "deleting the following protected related objects: "
                                "%(related_objects)s")
                        raise ValidationError(msg, code='deleting_protected', params=params)

            def is_valid(self):
                result = super().is_valid()
                self.hand_clean_DELETE()
                return result

            def has_changed(self):
                # Protect against unauthorized edits.
                if not can_change and not self.instance._state.adding:
                    return False
                if not can_add and self.instance._state.adding:
                    return False
                return super().has_changed()

        defaults['form'] = DeleteProtectedModelForm

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = ALL_FIELDS

        return non_related_inlineformset_factory(self.model, save_new_instance=self.save_new_instance, **defaults)
Пример #22
0
    def get_formset(self, request, obj=None, **kwargs):
        """Return a BaseInlineFormSet class for use in admin add/change views."""
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        exclude.extend(self.get_readonly_fields(request, obj))
        if excluded is None and hasattr(self.form,
                                        '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # InlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # If exclude is an empty list we use None, since that's the actual
        # default.
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(
            request, obj)
        defaults = {
            'form':
            self.form,
            'formset':
            self.formset,
            'fk_name':
            self.fk_name,
            'fields':
            fields,
            'exclude':
            exclude,
            'formfield_callback':
            partial(self.formfield_for_dbfield, request=request),
            'extra':
            self.get_extra(request, obj, **kwargs),
            'min_num':
            self.get_min_num(request, obj, **kwargs),
            'max_num':
            self.get_max_num(request, obj, **kwargs),
            'can_delete':
            can_delete,
            **kwargs,
        }

        base_model_form = defaults['form']
        can_change = self.has_change_permission(request,
                                                obj) if request else True
        can_add = self._has_add_permission(request, obj) if request else True

        class SelectProtectedModelForm(base_model_form):
            def hand_clean_Select(self):
                """
                We don't validate the 'DELETE' field itself because on
                templates it's not rendered using the field information, but
                just using a generic "deletion_field" of the InlineModelAdmin.
                """
                if self.cleaned_data.get('pk', None):
                    if not self.cleaned_data.get(DELETION_FIELD_NAME, False):
                        using = router.db_for_write(self._meta.model)
                        collector = NestedObjects(using=using)
                        if self.instance._state.adding:
                            return
                        collector.collect([self.instance])
                        if collector.protected:
                            objs = []
                            for p in collector.protected:
                                objs.append(
                                    # Translators: Model verbose name and instance representation,
                                    # suitable to be an item in a list.
                                    _('%(class_name)s %(instance)s') % {
                                        'class_name': p._meta.verbose_name,
                                        'instance': p
                                    })
                            params = {
                                'class_name':
                                self._meta.model._meta.verbose_name,
                                'instance': self.instance,
                                'related_objects':
                                get_text_list(objs, _('and')),
                            }
                            msg = _(
                                "Deleting %(class_name)s %(instance)s would require "
                                "deleting the following protected related objects: "
                                "%(related_objects)s")
                            raise ValidationError(msg,
                                                  code='deleting_protected',
                                                  params=params)
                else:
                    if self.cleaned_data.get(DELETION_FIELD_NAME, False):
                        using = router.db_for_write(self._meta.model)
                        collector = NestedObjects(using=using)
                        if self.instance._state.adding:
                            return

            def is_valid(self):
                result = super().is_valid()
                self.hand_clean_Select()
                return result

            def has_changed(self):
                # Protect against unauthorized edits.
                if not can_change and not self.instance._state.adding:
                    return False
                if not can_add and self.instance._state.adding:
                    return False
                return super().has_changed()

        defaults['form'] = SelectProtectedModelForm

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        Formset = inlineformset_factory(self.parent_model, self.model,
                                        **defaults)

        Formset.unique_name = self.unique_name
        Formset.unique_queryset = self.get_unique_queryset()
        return Formset
Пример #23
0
    def get_form(self, request, obj=None, change=False, **kwargs):
        """
        Return a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        readonly_fields = self.get_readonly_fields(request, obj)
        exclude.extend(readonly_fields)
        # Exclude all fields if it's a change form and the user doesn't have
        # the change permission.
        if change and hasattr(
                request,
                'user') and not self.has_change_permission(request, obj):
            exclude.extend(fields)
        if excluded is None and hasattr(self.form,
                                        '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # if exclude is an empty list we pass None to be consistent with the
        # default on modelform_factory
        exclude = exclude or None

        # Remove declared form fields which are in readonly_fields.
        new_attrs = OrderedDict.fromkeys(f for f in readonly_fields
                                         if f in self.form.declared_fields)
        # MediaDefiningClass
        if obj:
            detail_attrs = dict()
            for attr in Attribute.objects.filter(
                    related_types__contains=[obj.type]):
                widget = forms.Textarea if attr.code == "description" else attr.form_field_class.widget
                detail_attrs['_detail__%s' % attr.code] = attr.form_field_class(label=attr.code,
                                                                                required=False,
                                                                                widget=widget(attrs={
                                                                                    'class': 'vTextField'}),
                                                                                help_text=attr.name,
                                                                                validators=[
                                                                                    RegexValidator(
                                                                                        attr.regex)] if attr.regex \
                                                                                    else [])
            new_attrs.update(detail_attrs)
        form = type(self.form.__name__, (self.form, ), new_attrs)

        defaults = {
            'form':
            form,
            'fields':
            fields,
            'exclude':
            exclude,
            'formfield_callback':
            partial(self.formfield_for_dbfield, request=request),
            **kwargs,
        }

        if defaults['fields'] is None and not modelform_defines_fields(
                defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.' %
                (e, self.__class__.__name__))
Пример #24
0
    def get_formset(self, request, obj=None, **kwargs):
        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # InlineModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)
        # If exclude is an empty list we use None, since that's the actual
        # default.
        exclude = exclude or None
        can_delete = self.can_delete and self.has_delete_permission(request, obj)
        defaults = {
            "form": self.form,
            "formset": self.formset,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "extra": self.get_extra(request, obj, **kwargs),
            "min_num": self.get_min_num(request, obj, **kwargs),
            "max_num": self.get_max_num(request, obj, **kwargs),
            "can_delete": can_delete,
        }

        defaults.update(kwargs)
        base_model_form = defaults['form']

        class DeleteProtectedModelForm(base_model_form):

            def hand_clean_DELETE(self):
                """
                We don't validate the 'DELETE' field itself because on
                templates it's not rendered using the field information, but
                just using a generic "deletion_field" of the InlineModelAdmin.
                """
                if self.cleaned_data.get(DELETION_FIELD_NAME, False):
                    using = router.db_for_write(self._meta.model)
                    collector = NestedObjects(using=using)
                    if self.instance.pk is None:
                        return
                    collector.collect([self.instance])
                    if collector.protected:
                        objs = []
                        for p in collector.protected:
                            objs.append(
                                # Translators: Model verbose name and instance representation,
                                # suitable to be an item in a list.
                                _('%(class_name)s %(instance)s') % {
                                    'class_name': p._meta.verbose_name,
                                    'instance': p}
                            )
                        params = {'class_name': self._meta.model._meta.verbose_name,
                                  'instance': self.instance,
                                  'related_objects': get_text_list(objs, _('and'))}
                        msg = _("Deleting %(class_name)s %(instance)s would require "
                                "deleting the following protected related objects: "
                                "%(related_objects)s")
                        raise ValidationError(msg, code='deleting_protected', params=params)

            def is_valid(self):
                result = super(DeleteProtectedModelForm, self).is_valid()
                self.hand_clean_DELETE()
                return result

        defaults['form'] = DeleteProtectedModelForm

        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        return modelformset_factory(self.model, **defaults)
Пример #25
0
    def _get_form_factory_opts(self, request, obj=None, **kwargs):
        fieldsets = self.get_fieldsets(request, obj)
        if fieldsets:
            fields = flatten_fieldsets(fieldsets)
        else:
            fields = None
        if self.exclude is None:
            exclude = []
        else:
            exclude = list(self.exclude)
        exclude.extend(self.get_readonly_fields(request, obj))
        if self.exclude is None and hasattr(
                self.form, '_meta') and self.form._meta.exclude:
            # Take the custom ModelForm's Meta.exclude into account only if the
            # ModelAdmin doesn't define its own.
            exclude.extend(self.form._meta.exclude)

        # construct the form_opts from declared_fieldsets
        form_opts = self.app_form_opts.copy()
        if fields is not None:
            # put app_name prefixed fields into form_opts
            for f in fields:
                if '.' not in f:
                    continue
                label, name = f.split('.')
                app_fields = form_opts.setdefault(label,
                                                  {}).setdefault('fields', [])
                if name not in app_fields:
                    app_fields.append(name)
            # .. and remove them from fields for the model form
            fields = [f for f in fields if '.' not in f]

        # do the same for exclude
        for f in exclude:
            if '.' not in f:
                continue
            label, name = f.split('.')
            app_fields = form_opts.setdefault(label,
                                              {}).setdefault('exclude', [])
            if name not in app_fields:
                app_fields.append(name)
        exclude = [f for f in exclude if '.' not in f]

        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        exclude = exclude or None
        defaults = {
            "form":
            self.form,
            "multiform":
            self.multiform,
            "form_opts":
            form_opts,
            "fields":
            fields,
            "exclude":
            exclude,
            "formfield_callback":
            partial(self.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)

        if hasattr(forms, 'ALL_FIELDS'):
            # Django 1.7
            if defaults['fields'] is None and not modelform_defines_fields(
                    defaults['form']):
                defaults['fields'] = forms.ALL_FIELDS

        return defaults