Exemple #1
0
 def get_formset(self, request, obj=None):
     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))
     exclude = exclude or None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "can_delete": self.can_delete,
         "can_order": False,
         "fields": fields,
         "max_num": self.max_num,
         "exclude": exclude
     }
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #2
0
    def get_readonly_fields(self, request, obj=None):
        from django.contrib.admin.options import modelform_factory, flatten_fieldsets
        from django.utils.functional import curry

        if not hasattr(self, "_readonly_fields"):
            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.readonly_fields)

            # 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": fields,
                "exclude": exclude,
                "formfield_callback": curry(self.formfield_for_dbfield, request=request),
            }
            self._readonly_fields = modelform_factory(self.model, **defaults).base_fields
        return self._readonly_fields.keys()
    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)
Exemple #4
0
 def get_formset(self, request, obj=None):
     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))
     exclude = exclude or None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "can_delete": self.can_delete,
         "can_order": False,
         "fields": fields,
         "max_num": self.max_num,
         "exclude": exclude
     }
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #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)
Exemple #6
0
    def get_readonly_fields(self, request, obj=None):
        from django.contrib.admin.options import modelform_factory, flatten_fieldsets
        from django.utils.functional import curry

        if not hasattr(self, "_readonly_fields"):
            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.readonly_fields)

            # 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":
                fields,
                "exclude":
                exclude,
                "formfield_callback":
                curry(self.formfield_for_dbfield, request=request),
            }
            self._readonly_fields = modelform_factory(self.model,
                                                      **defaults).base_fields
        return self._readonly_fields.keys()
Exemple #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)
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #8
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)
     return generic_inlineformset_factory(self.model, **defaults)
    def _group_fieldsets(self, fieldsets):
        # Fieldsets are not grouped by default. The function is activated by
        # setting TranslationAdmin.group_fieldsets to True. If the admin class
        # already defines a fieldset, we leave it alone and assume the author
        # has done whatever grouping for translated fields they desire.
        if self.group_fieldsets is True:
            flattened_fieldsets = flatten_fieldsets(fieldsets)

            # Create a fieldset to group each translated field's localized fields
            fields = sorted((f for f in self.opts.get_fields() if f.concrete))
            untranslated_fields = [
                f.name for f in fields if (
                    # Exclude the primary key field
                    f is not self.opts.auto_field
                    # Exclude non-editable fields
                    and f.editable
                    # Exclude the translation fields
                    and not hasattr(f, 'translated_field')
                    # Honour field arguments. We rely on the fact that the
                    # passed fieldsets argument is already fully filtered
                    # and takes options like exclude into account.
                    and f.name in flattened_fieldsets)
            ]
            # TODO: Allow setting a label
            fieldsets = ([(
                '',
                {
                    'fields': untranslated_fields
                },
            )] if untranslated_fields else [])

            temp_fieldsets = {}
            for orig_field, trans_fields in self.trans_opts.fields.items():
                trans_fieldnames = [
                    f.name for f in sorted(trans_fields, key=lambda x: x.name)
                ]
                if any(f in trans_fieldnames for f in flattened_fieldsets):
                    # Extract the original field's verbose_name for use as this
                    # fieldset's label - using gettext_lazy in your model
                    # declaration can make that translatable.
                    label = self.model._meta.get_field(
                        orig_field).verbose_name.capitalize()
                    temp_fieldsets[orig_field] = (
                        label,
                        {
                            'fields': trans_fieldnames,
                            'classes': ('mt-fieldset', )
                        },
                    )

            fields_order = unique(f.translated_field.name
                                  for f in self.opts.fields
                                  if hasattr(f, 'translated_field')
                                  and f.name in flattened_fieldsets)
            for field_name in fields_order:
                fieldsets.append(temp_fieldsets.pop(field_name))
            assert not temp_fieldsets  # cleaned

        return fieldsets
Exemple #10
0
 def get_readonly_fields(self, request, obj=None):
     if obj is not None:
         if not request.user.is_superuser:
             if request.user.username == obj.username or not obj.is_admin:
                 return self.readonly_fields + ('is_superuser',)
             else:
                 return self.readonly_fields + tuple(flatten_fieldsets(self.get_fieldsets(request, obj)))
     return self.readonly_fields
Exemple #11
0
 def get_readonly_fields(self, request, obj=None):
     if obj is not None:
         if not request.user.is_superuser:
             if request.user.username == obj.username or not obj.is_admin:
                 return self.readonly_fields + ('is_superuser', )
             else:
                 return self.readonly_fields + tuple(
                     flatten_fieldsets(self.get_fieldsets(request, obj)))
     return self.readonly_fields
Exemple #12
0
    def get_readonly_fields(self, request, obj=None):
        user = request.user
        if user.is_staff and not user.is_superuser:
            if self.fieldsets:
                return flatten_fieldsets(self.fieldsets or [])
            else:
                return list(
                    set([field.name for field in self.opts.local_fields] +
                        [field.name
                         for field in self.opts.local_many_to_many]))

        return super().get_readonly_fields(request, obj)
    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)
    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)
    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)
    def _group_fieldsets(self, fieldsets):
        # Fieldsets are not grouped by default. The function is activated by
        # setting TranslationAdmin.group_fieldsets to True. If the admin class
        # already defines a fieldset, we leave it alone and assume the author
        # has done whatever grouping for translated fields they desire.
        if not self.declared_fieldsets and self.group_fieldsets is True:
            flattened_fieldsets = flatten_fieldsets(fieldsets)

            # Create a fieldset to group each translated field's localized fields
            untranslated_fields = [
                f.name
                for f in self.opts.fields
                if (
                    # Exclude the primary key field
                    f is not self.opts.auto_field
                    # Exclude non-editable fields
                    and f.editable
                    # Exclude the translation fields
                    and not hasattr(f, "translated_field")
                    # Honour field arguments. We rely on the fact that the
                    # passed fieldsets argument is already fully filtered
                    # and takes options like exclude into account.
                    and f.name in flattened_fieldsets
                )
            ]
            # TODO: Allow setting a label
            fieldsets = [("", {"fields": untranslated_fields})] if untranslated_fields else []

            temp_fieldsets = {}
            for orig_field, trans_fields in self.trans_opts.fields.items():
                trans_fieldnames = [f.name for f in sorted(trans_fields, key=lambda x: x.name)]
                if any(f in trans_fieldnames for f in flattened_fieldsets):
                    # Extract the original field's verbose_name for use as this
                    # fieldset's label - using ugettext_lazy in your model
                    # declaration can make that translatable.
                    label = self.model._meta.get_field(orig_field).verbose_name
                    temp_fieldsets[orig_field] = (label, {"fields": trans_fieldnames, "classes": ("mt-fieldset",)})

            fields_order = unique(
                f.translated_field.name
                for f in self.opts.fields
                if hasattr(f, "translated_field") and f.name in flattened_fieldsets
            )
            for field_name in fields_order:
                fieldsets.append(temp_fieldsets.pop(field_name))
            assert not temp_fieldsets  # cleaned

        return fieldsets
Exemple #17
0
 def get_formset(self, request, obj=None):
     if self.declared_fieldsets:
         fields = flatten_fieldsets(self.declared_fieldsets)
     else:
         fields = None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "can_delete": True,
         "can_order": False,
         "fields": fields,
     }
     return generic_inlineformset_factory(self.model, **defaults)
 def get_formset(self, request, obj=None):
     if self.declared_fieldsets:
         fields = flatten_fieldsets(self.declared_fieldsets)
     else:
         fields = None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "can_delete": True,
         "can_order": False,
         "fields": fields,
     }
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #19
0
    def get_readonly_fields(self, request, obj=None):

        read_only, created = Group.objects.get_or_create(
            name=self.read_only_group_name
        )
        if obj and read_only in request.user.groups.all():

            if self.declared_fieldsets:
                fieldsets = self.declared_fieldsets
                self.remove_from_fieldsets(fieldsets, self.remove_fields_if_read_only)
                fields = flatten_fieldsets(fieldsets)
            else:
                fields = list(set(
                    [field.name for field in self.opts.local_fields] +
                    [field.name for field in self.opts.local_many_to_many]
                ))
            return fields

        return self.readonly_fields
Exemple #20
0
 def validate_fieldsets(self, cls, model):
     " Validate that fieldsets is properly formatted and doesn't contain duplicates. "
     from django.contrib.admin.options import flatten_fieldsets
     if cls.fieldsets: # default value is None
         check_isseq(cls, 'fieldsets', cls.fieldsets)
         for idx, fieldset in enumerate(cls.fieldsets):
             check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
             if len(fieldset) != 2:
                 raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                         "have exactly two elements." % (cls.__name__, idx))
             check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
             if 'fields' not in fieldset[1]:
                 raise ImproperlyConfigured("'fields' key is required in "
                         "%s.fieldsets[%d][1] field options dict."
                         % (cls.__name__, idx))
             self.check_field_spec(cls, model, fieldset[1]['fields'], "fieldsets[%d][1]['fields']" % idx)
         flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
         if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
             raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__)
Exemple #21
0
    def get_readonly_fields(self, request, obj=None):

        read_only, created = Group.objects.get_or_create(
            name=self.read_only_group_name)
        if obj and read_only in request.user.groups.all():

            if self.declared_fieldsets:
                fieldsets = self.declared_fieldsets
                self.remove_from_fieldsets(fieldsets,
                                           self.remove_fields_if_read_only)
                fields = flatten_fieldsets(fieldsets)
            else:
                fields = list(
                    set([field.name for field in self.opts.local_fields] +
                        [field.name
                         for field in self.opts.local_many_to_many]))
            return fields

        return self.readonly_fields
    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)
Exemple #23
0
 def validate_fieldsets(self, cls, model):
     " Validate that fieldsets is properly formatted and doesn't contain duplicates. "
     from django.contrib.admin.options import flatten_fieldsets
     if cls.fieldsets: # default value is None
         check_isseq(cls, 'fieldsets', cls.fieldsets)
         for idx, fieldset in enumerate(cls.fieldsets):
             check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
             if len(fieldset) != 2:
                 raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                         "have exactly two elements." % (cls.__name__, idx))
             check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
             if 'fields' not in fieldset[1]:
                 raise ImproperlyConfigured("'fields' key is required in "
                         "%s.fieldsets[%d][1] field options dict."
                         % (cls.__name__, idx))
             self.check_field_spec(cls, model, fieldset[1]['fields'], "fieldsets[%d][1]['fields']" % idx)
         flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
         if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
             raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__)
Exemple #24
0
def validate_base(cls, model):
    opts = model._meta

    # fields
    if cls.fields: # default value is None
        check_isseq(cls, 'fields', cls.fields)
        validate_fields_spec(cls, model, opts, cls.fields, 'fields')
        if cls.fieldsets:
            raise ImproperlyConfigured('Both fieldsets and fields are specified in %s.' % cls.__name__)
        if len(cls.fields) > len(set(cls.fields)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fields' % cls.__name__)

    # fieldsets
    if cls.fieldsets: # default value is None
        check_isseq(cls, 'fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                        "have exactly two elements." % (cls.__name__, idx))
            check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured("'fields' key is required in "
                        "%s.fieldsets[%d][1] field options dict."
                        % (cls.__name__, idx))
            validate_fields_spec(cls, model, opts, fieldset[1]['fields'], "fieldsets[%d][1]['fields']" % idx)
        flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
        if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__)

    # exclude
    if cls.exclude: # default value is None
        check_isseq(cls, 'exclude', cls.exclude)
        for field in cls.exclude:
            #~ check_formfield(cls, model, opts, 'exclude', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
        if len(cls.exclude) > len(set(cls.exclude)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.exclude' % cls.__name__)
    def _group_fieldsets(self, fieldsets):
        # Fieldsets are not grouped by default. The function is activated by
        # setting TranslationAdmin.group_fieldsets to True. If the admin class
        # already defines a fieldset, we leave it alone and assume the author
        # has done whatever grouping for translated fields they desire.
        if not self.declared_fieldsets and self.group_fieldsets is True:
            flattened_fieldsets = flatten_fieldsets(fieldsets)

            # Create a fieldset to group each translated field's localized fields
            untranslated_fields = [
                f.name for f in self.opts.fields if (
                    # Exclude the primary key field
                    f is not self.opts.auto_field
                    # Exclude non-editable fields
                    and f.editable
                    # Exclude the translation fields
                    # TODO: I already miss localized_fieldnames_rev here ;)
                    and f not in [
                        k for l in [list(j) for i in self.trans_opts.fields.items() for
                                    j in i[1:]] for k in l]
                    # Honour field arguments. We rely on the fact that the
                    # passed fieldsets argument is already fully filtered
                    # and takes options like exclude into account.
                    and f.name in flattened_fieldsets
                )
            ]
            # TODO: Allow setting a label
            fieldsets = [('', {'fields': untranslated_fields},)] if untranslated_fields else []

            for orig_field, trans_fields in self.trans_opts.fields.items():
                trans_fieldnames = [f.name for f in sorted(trans_fields, key=lambda x: x.name)]
                if any(f in trans_fieldnames for f in flattened_fieldsets):
                    # Extract the original field's verbose_name for use as this
                    # fieldset's label - using ugettext_lazy in your model
                    # declaration can make that translatable.
                    label = self.model._meta.get_field(orig_field).verbose_name
                    fieldsets.append((label, {
                        'fields': trans_fieldnames,
                        'classes': ('mt-fieldset',)
                    }))

        return fieldsets
Exemple #26
0
 def get_formset(self, request, obj=None):
     setattr(self.form, '_magic_user', request.user) # magic variable passing to form
     setattr(self, '_magic_user', request.user) # magic variable
     if self.declared_fieldsets:
         fields = flatten_fieldsets(self.declared_fieldsets)
     else:
         fields = None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "max_num": self.max_num,
         "can_delete": True,
         "can_order": False,
         "fields": fields,
     }
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #27
0
 def get_formset(self, request, obj=None):
     setattr(self.form, '_magic_user', request.user) # magic variable passing to form
     setattr(self, '_magic_user', request.user) # magic variable
     if self.declared_fieldsets:
         fields = flatten_fieldsets(self.declared_fieldsets)
     else:
         fields = None
     defaults = {
         "ct_field": self.ct_field,
         "fk_field": self.ct_fk_field,
         "form": self.form,
         "formfield_callback": self.formfield_for_dbfield,
         "formset": self.formset,
         "extra": self.extra,
         "max_num": self.max_num,
         "can_delete": True,
         "can_order": False,
         "fields": fields,
     }
     return generic_inlineformset_factory(self.model, **defaults)
Exemple #28
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

        try:
            return documentform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
                             % (e, self.__class__.__name__))
Exemple #29
0
def validate_base(cls, model):
    opts = model._meta

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        check_isseq(cls, 'raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = get_field(cls, model, opts, 'raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "'%s.raw_id_fields[%d]', '%s' must "
                    "be either a ForeignKey or ManyToManyField." %
                    (cls.__name__, idx, field))

    # fields
    if cls.fields:  # default value is None
        check_isseq(cls, 'fields', cls.fields)
        for field in cls.fields:
            if field in cls.readonly_fields:
                # Stuff can be put in fields that isn't actually a model field
                # if it's in readonly_fields, readonly_fields will handle the
                # validation of such things.
                continue
            check_formfield(cls, model, opts, 'fields', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
            if isinstance(f, models.ManyToManyField
                          ) and not f.rel.through._meta.auto_created:
                raise ImproperlyConfigured(
                    "'%s.fields' can't include the ManyToManyField "
                    "field '%s' because '%s' manually specifies "
                    "a 'through' model." % (cls.__name__, field, field))
        if cls.fieldsets:
            raise ImproperlyConfigured(
                'Both fieldsets and fields are specified in %s.' %
                cls.__name__)
        if len(cls.fields) > len(set(cls.fields)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.fields' % cls.__name__)

    # fieldsets
    if cls.fieldsets:  # default value is None
        check_isseq(cls, 'fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                                           "have exactly two elements." %
                                           (cls.__name__, idx))
            check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured(
                    "'fields' key is required in "
                    "%s.fieldsets[%d][1] field options dict." %
                    (cls.__name__, idx))
            for fields in fieldset[1]['fields']:
                # The entry in fields might be a tuple. If it is a standalone
                # field, make it into a tuple to make processing easier.
                if type(fields) != tuple:
                    fields = (fields, )
                for field in fields:
                    if field in cls.readonly_fields:
                        # Stuff can be put in fields that isn't actually a
                        # model field if it's in readonly_fields,
                        # readonly_fields will handle the validation of such
                        # things.
                        continue
                    check_formfield(cls, model, opts,
                                    "fieldsets[%d][1]['fields']" % idx, field)
                    try:
                        f = opts.get_field(field)
                        if isinstance(
                                f, models.ManyToManyField
                        ) and not f.rel.through._meta.auto_created:
                            raise ImproperlyConfigured(
                                "'%s.fieldsets[%d][1]['fields']' "
                                "can't include the ManyToManyField field '%s' because "
                                "'%s' manually specifies a 'through' model." %
                                (cls.__name__, idx, field, field))
                    except models.FieldDoesNotExist:
                        # If we can't find a field on the model that matches,
                        # it could be an extra field on the form.
                        pass
        flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
        if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.fieldsets' % cls.__name__)

    # exclude
    if cls.exclude:  # default value is None
        check_isseq(cls, 'exclude', cls.exclude)
        for field in cls.exclude:
            check_formfield(cls, model, opts, 'exclude', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
        if len(cls.exclude) > len(set(cls.exclude)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.exclude' % cls.__name__)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                                   "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        check_isseq(cls, 'filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = get_field(cls, model, opts, 'filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_vertical[%d]' must be "
                                           "a ManyToManyField." %
                                           (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        check_isseq(cls, 'filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = get_field(cls, model, opts, 'filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured(
                    "'%s.filter_horizontal[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        check_isdict(cls, 'radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = get_field(cls, model, opts, 'radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured(
                    "'%s.radio_fields['%s']' "
                    "is neither an instance of ForeignKey nor does "
                    "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured(
                    "'%s.radio_fields['%s']' "
                    "is neither admin.HORIZONTAL nor admin.VERTICAL." %
                    (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        check_isdict(cls, 'prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = get_field(cls, model, opts, 'prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                              models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "'%s.prepopulated_fields['%s']' "
                    "is either a DateTimeField, ForeignKey or "
                    "ManyToManyField. This isn't allowed." %
                    (cls.__name__, field))
            check_isseq(cls, "prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                get_field(cls, model, opts,
                          "prepopulated_fields['%s'][%d]" % (field, idx), f)
Exemple #30
0
def validate_base(cls, model):
    opts = model._meta

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        check_isseq(cls, 'raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = get_field(cls, model, opts, 'raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured("'%s.raw_id_fields[%d]', '%s' must "
                        "be either a ForeignKey or ManyToManyField."
                        % (cls.__name__, idx, field))

    # fields
    if cls.fields: # default value is None
        check_isseq(cls, 'fields', cls.fields)
        for field in cls.fields:
            if field in cls.readonly_fields:
                # Stuff can be put in fields that isn't actually a model field
                # if it's in readonly_fields, readonly_fields will handle the
                # validation of such things.
                continue
            check_formfield(cls, model, opts, 'fields', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
            if isinstance(f, models.ManyToManyField) and not f.rel.through._meta.auto_created:
                raise ImproperlyConfigured("'%s.fields' can't include the ManyToManyField "
                    "field '%s' because '%s' manually specifies "
                    "a 'through' model." % (cls.__name__, field, field))
        if cls.fieldsets:
            raise ImproperlyConfigured('Both fieldsets and fields are specified in %s.' % cls.__name__)
        if len(cls.fields) > len(set(cls.fields)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fields' % cls.__name__)

    # fieldsets
    if cls.fieldsets: # default value is None
        check_isseq(cls, 'fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                        "have exactly two elements." % (cls.__name__, idx))
            check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured("'fields' key is required in "
                        "%s.fieldsets[%d][1] field options dict."
                        % (cls.__name__, idx))
            for fields in fieldset[1]['fields']:
                # The entry in fields might be a tuple. If it is a standalone
                # field, make it into a tuple to make processing easier.
                if type(fields) != tuple:
                    fields = (fields,)
                for field in fields:
                    if field in cls.readonly_fields:
                        # Stuff can be put in fields that isn't actually a
                        # model field if it's in readonly_fields,
                        # readonly_fields will handle the validation of such
                        # things.
                        continue
                    check_formfield(cls, model, opts, "fieldsets[%d][1]['fields']" % idx, field)
                    try:
                        f = opts.get_field(field)
                        if isinstance(f, models.ManyToManyField) and not f.rel.through._meta.auto_created:
                            raise ImproperlyConfigured("'%s.fieldsets[%d][1]['fields']' "
                                "can't include the ManyToManyField field '%s' because "
                                "'%s' manually specifies a 'through' model." % (
                                    cls.__name__, idx, field, field))
                    except models.FieldDoesNotExist:
                        # If we can't find a field on the model that matches,
                        # it could be an extra field on the form.
                        pass
        flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
        if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__)

    # exclude
    if cls.exclude: # default value is None
        check_isseq(cls, 'exclude', cls.exclude)
        for field in cls.exclude:
            check_formfield(cls, model, opts, 'exclude', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
        if len(cls.exclude) > len(set(cls.exclude)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.exclude' % cls.__name__)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        check_isseq(cls, 'filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = get_field(cls, model, opts, 'filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_vertical[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        check_isseq(cls, 'filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = get_field(cls, model, opts, 'filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_horizontal[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        check_isdict(cls, 'radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = get_field(cls, model, opts, 'radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured("'%s.radio_fields['%s']' "
                        "is neither an instance of ForeignKey nor does "
                        "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured("'%s.radio_fields['%s']' "
                        "is neither admin.HORIZONTAL nor admin.VERTICAL."
                        % (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        check_isdict(cls, 'prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = get_field(cls, model, opts, 'prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                models.ManyToManyField)):
                raise ImproperlyConfigured("'%s.prepopulated_fields['%s']' "
                        "is either a DateTimeField, ForeignKey or "
                        "ManyToManyField. This isn't allowed."
                        % (cls.__name__, field))
            check_isseq(cls, "prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                get_field(cls, model, opts, "prepopulated_fields['%s'][%d]" % (field, idx), f)
def validate_base(cls, model):
    opts = model._meta

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        check_isseq(cls, 'raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = get_field(cls, model, opts, 'raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured("'%s.raw_id_fields[%d]', '%s' must "
                        "be either a ForeignKey or ManyToManyField."
                        % (cls.__name__, idx, field))

    # fields
    if cls.fields: # default value is None
        check_isseq(cls, 'fields', cls.fields)
        for field in cls.fields:
            check_formfield(cls, model, opts, 'fields', field)
        if cls.fieldsets:
            raise ImproperlyConfigured('Both fieldsets and fields are specified in %s.' % cls.__name__)
        if len(cls.fields) > len(set(cls.fields)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fields' % cls.__name__)

    # fieldsets
    if cls.fieldsets: # default value is None
        check_isseq(cls, 'fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                        "have exactly two elements." % (cls.__name__, idx))
            check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured("'fields' key is required in "
                        "%s.fieldsets[%d][1] field options dict."
                        % (cls.__name__, idx))
        flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
        if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
            raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__)
        for field in flattened_fieldsets:
            check_formfield(cls, model, opts, "fieldsets[%d][1]['fields']" % idx, field)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        check_isseq(cls, 'filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = get_field(cls, model, opts, 'filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_vertical[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        check_isseq(cls, 'filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = get_field(cls, model, opts, 'filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_horizontal[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        check_isdict(cls, 'radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = get_field(cls, model, opts, 'radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured("'%s.radio_fields['%s']' "
                        "is neither an instance of ForeignKey nor does "
                        "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured("'%s.radio_fields['%s']' "
                        "is neither admin.HORIZONTAL nor admin.VERTICAL."
                        % (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        check_isdict(cls, 'prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = get_field(cls, model, opts, 'prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                models.ManyToManyField)):
                raise ImproperlyConfigured("'%s.prepopulated_fields['%s']' "
                        "is either a DateTimeField, ForeignKey or "
                        "ManyToManyField. This isn't allowed."
                        % (cls.__name__, field))
            check_isseq(cls, "prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                get_field(cls, model, opts, "prepopulated_fields['%s'][%d]" % (field, idx), f)
Exemple #32
0
def _validate_base(cls, model):
    opts = model._meta
    # currying is expensive, use wrappers instead
    def _check_istuplew(label, obj):
        _check_istuple(cls, label, obj)

    def _check_isdictw(label, obj):
        _check_isdict(cls, label, obj)

    def _check_field_existsw(label, field):
        return _check_field_exists(cls, model, opts, label, field)
    
    def _check_form_field_existsw(label, field):
        return _check_form_field_exists(cls, model, opts, label, field)

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        _check_istuplew('raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = _check_field_existsw('raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured("`%s.raw_id_fields[%d]`, `%s` must "
                        "be either a ForeignKey or ManyToManyField."
                        % (cls.__name__, idx, field))

    # fields
    if cls.fields: # default value is None
        _check_istuplew('fields', cls.fields)
        for field in cls.fields:
            _check_form_field_existsw('fields', field)
        if cls.fieldsets:
            raise ImproperlyConfigured('Both fieldsets and fields are specified in %s.' % cls.__name__)

    # fieldsets
    if cls.fieldsets: # default value is None
        _check_istuplew('fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            _check_istuplew('fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("`%s.fieldsets[%d]` does not "
                        "have exactly two elements." % (cls.__name__, idx))
            _check_isdictw('fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured("`fields` key is required in "
                        "%s.fieldsets[%d][1] field options dict."
                        % (cls.__name__, idx))
        for field in flatten_fieldsets(cls.fieldsets):
            _check_form_field_existsw("fieldsets[%d][1]['fields']" % idx, field)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        _check_istuplew('filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = _check_field_existsw('filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("`%s.filter_vertical[%d]` must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        _check_istuplew('filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = _check_field_existsw('filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("`%s.filter_horizontal[%d]` must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        _check_isdictw('radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = _check_field_existsw('radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured("`%s.radio_fields['%s']` "
                        "is neither an instance of ForeignKey nor does "
                        "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured("`%s.radio_fields['%s']` "
                        "is neither admin.HORIZONTAL nor admin.VERTICAL."
                        % (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        _check_isdictw('prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = _check_field_existsw('prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                models.ManyToManyField)):
                raise ImproperlyConfigured("`%s.prepopulated_fields['%s']` "
                        "is either a DateTimeField, ForeignKey or "
                        "ManyToManyField. This isn't allowed."
                        % (cls.__name__, field))
            _check_istuplew("prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                _check_field_existsw("prepopulated_fields['%s'][%d]"
                        % (f, idx), f)
 def get_readonly_fields(self, request, obj=None):
     if obj:
         return 'model',
     else:
         return set(flatten_fieldsets(self.get_fieldsets(request, obj))) - set(('model', 'admin_site'))
Exemple #34
0
    def get_formset(self, request, obj=None, **kwargs):
        """Returns 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))
        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,
            "embedded_name": self.parent_field_name,
            "fields": fields,
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "extra": self.get_extra(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):
                    collector = NestedObjects()
                    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'] = None

        return embeddedformset_factory(self.model, self.parent_model, **defaults)
Exemple #35
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)
Exemple #36
0
def validate_base(cls, model):
    opts = model._meta

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        check_isseq(cls, 'raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = get_field(cls, model, opts, 'raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "'%s.raw_id_fields[%d]', '%s' must "
                    "be either a ForeignKey or ManyToManyField." %
                    (cls.__name__, idx, field))

    # fields
    if cls.fields:  # default value is None
        check_isseq(cls, 'fields', cls.fields)
        validate_fields_spec(cls, model, opts, cls.fields, 'fields')
        if cls.fieldsets:
            raise ImproperlyConfigured(
                'Both fieldsets and fields are specified in %s.' %
                cls.__name__)
        if len(cls.fields) > len(set(cls.fields)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.fields' % cls.__name__)

    # fieldsets
    if cls.fieldsets:  # default value is None
        check_isseq(cls, 'fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            check_isseq(cls, 'fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("'%s.fieldsets[%d]' does not "
                                           "have exactly two elements." %
                                           (cls.__name__, idx))
            check_isdict(cls, 'fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured(
                    "'fields' key is required in "
                    "%s.fieldsets[%d][1] field options dict." %
                    (cls.__name__, idx))
            validate_fields_spec(cls, model, opts, fieldset[1]['fields'],
                                 "fieldsets[%d][1]['fields']" % idx)
        flattened_fieldsets = flatten_fieldsets(cls.fieldsets)
        if len(flattened_fieldsets) > len(set(flattened_fieldsets)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.fieldsets' % cls.__name__)

    # exclude
    if cls.exclude:  # default value is None
        check_isseq(cls, 'exclude', cls.exclude)
        for field in cls.exclude:
            check_formfield(cls, model, opts, 'exclude', field)
            try:
                f = opts.get_field(field)
            except models.FieldDoesNotExist:
                # If we can't find a field on the model that matches,
                # it could be an extra field on the form.
                continue
        if len(cls.exclude) > len(set(cls.exclude)):
            raise ImproperlyConfigured(
                'There are duplicate field(s) in %s.exclude' % cls.__name__)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                                   "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        check_isseq(cls, 'filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = get_field(cls, model, opts, 'filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("'%s.filter_vertical[%d]' must be "
                                           "a ManyToManyField." %
                                           (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        check_isseq(cls, 'filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = get_field(cls, model, opts, 'filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured(
                    "'%s.filter_horizontal[%d]' must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        check_isdict(cls, 'radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = get_field(cls, model, opts, 'radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured(
                    "'%s.radio_fields['%s']' "
                    "is neither an instance of ForeignKey nor does "
                    "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured(
                    "'%s.radio_fields['%s']' "
                    "is neither admin.HORIZONTAL nor admin.VERTICAL." %
                    (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        check_isdict(cls, 'prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = get_field(cls, model, opts, 'prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                              models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "'%s.prepopulated_fields['%s']' "
                    "is either a DateTimeField, ForeignKey or "
                    "ManyToManyField. This isn't allowed." %
                    (cls.__name__, field))
            check_isseq(cls, "prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                get_field(cls, model, opts,
                          "prepopulated_fields['%s'][%d]" % (field, idx), f)
Exemple #37
0
def _validate_base(cls, model):
    opts = model._meta

    # currying is expensive, use wrappers instead
    def _check_istuplew(label, obj):
        _check_istuple(cls, label, obj)

    def _check_isdictw(label, obj):
        _check_isdict(cls, label, obj)

    def _check_field_existsw(label, field):
        return _check_field_exists(cls, model, opts, label, field)

    def _check_form_field_existsw(label, field):
        return _check_form_field_exists(cls, model, opts, label, field)

    # raw_id_fields
    if hasattr(cls, 'raw_id_fields'):
        _check_istuplew('raw_id_fields', cls.raw_id_fields)
        for idx, field in enumerate(cls.raw_id_fields):
            f = _check_field_existsw('raw_id_fields', field)
            if not isinstance(f, (models.ForeignKey, models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "`%s.raw_id_fields[%d]`, `%s` must "
                    "be either a ForeignKey or ManyToManyField." %
                    (cls.__name__, idx, field))

    # fields
    if cls.fields:  # default value is None
        _check_istuplew('fields', cls.fields)
        for field in cls.fields:
            _check_form_field_existsw('fields', field)
        if cls.fieldsets:
            raise ImproperlyConfigured(
                'Both fieldsets and fields are specified in %s.' %
                cls.__name__)

    # fieldsets
    if cls.fieldsets:  # default value is None
        _check_istuplew('fieldsets', cls.fieldsets)
        for idx, fieldset in enumerate(cls.fieldsets):
            _check_istuplew('fieldsets[%d]' % idx, fieldset)
            if len(fieldset) != 2:
                raise ImproperlyConfigured("`%s.fieldsets[%d]` does not "
                                           "have exactly two elements." %
                                           (cls.__name__, idx))
            _check_isdictw('fieldsets[%d][1]' % idx, fieldset[1])
            if 'fields' not in fieldset[1]:
                raise ImproperlyConfigured(
                    "`fields` key is required in "
                    "%s.fieldsets[%d][1] field options dict." %
                    (cls.__name__, idx))
        for field in flatten_fieldsets(cls.fieldsets):
            _check_form_field_existsw("fieldsets[%d][1]['fields']" % idx,
                                      field)

    # form
    if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm):
        raise ImproperlyConfigured("%s.form does not inherit from "
                                   "BaseModelForm." % cls.__name__)

    # filter_vertical
    if hasattr(cls, 'filter_vertical'):
        _check_istuplew('filter_vertical', cls.filter_vertical)
        for idx, field in enumerate(cls.filter_vertical):
            f = _check_field_existsw('filter_vertical', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured("`%s.filter_vertical[%d]` must be "
                                           "a ManyToManyField." %
                                           (cls.__name__, idx))

    # filter_horizontal
    if hasattr(cls, 'filter_horizontal'):
        _check_istuplew('filter_horizontal', cls.filter_horizontal)
        for idx, field in enumerate(cls.filter_horizontal):
            f = _check_field_existsw('filter_horizontal', field)
            if not isinstance(f, models.ManyToManyField):
                raise ImproperlyConfigured(
                    "`%s.filter_horizontal[%d]` must be "
                    "a ManyToManyField." % (cls.__name__, idx))

    # radio_fields
    if hasattr(cls, 'radio_fields'):
        _check_isdictw('radio_fields', cls.radio_fields)
        for field, val in cls.radio_fields.items():
            f = _check_field_existsw('radio_fields', field)
            if not (isinstance(f, models.ForeignKey) or f.choices):
                raise ImproperlyConfigured(
                    "`%s.radio_fields['%s']` "
                    "is neither an instance of ForeignKey nor does "
                    "have choices set." % (cls.__name__, field))
            if not val in (HORIZONTAL, VERTICAL):
                raise ImproperlyConfigured(
                    "`%s.radio_fields['%s']` "
                    "is neither admin.HORIZONTAL nor admin.VERTICAL." %
                    (cls.__name__, field))

    # prepopulated_fields
    if hasattr(cls, 'prepopulated_fields'):
        _check_isdictw('prepopulated_fields', cls.prepopulated_fields)
        for field, val in cls.prepopulated_fields.items():
            f = _check_field_existsw('prepopulated_fields', field)
            if isinstance(f, (models.DateTimeField, models.ForeignKey,
                              models.ManyToManyField)):
                raise ImproperlyConfigured(
                    "`%s.prepopulated_fields['%s']` "
                    "is either a DateTimeField, ForeignKey or "
                    "ManyToManyField. This isn't allowed." %
                    (cls.__name__, field))
            _check_istuplew("prepopulated_fields['%s']" % field, val)
            for idx, f in enumerate(val):
                _check_field_existsw(
                    "prepopulated_fields['%s'][%d]" % (f, idx), f)