Пример #1
0
    def __init__(
            self,
            *,
            payment_modes,
            empty_label=_("Choisissez votre moyen de paiement"),
            required=True,
            initial=None,
            label=_("Mode de paiement"),
            **kwargs,
    ):

        self._payment_modes = [
            PAYMENT_MODES[p] if isinstance(p, str) else p
            for p in payment_modes
        ]

        if required:
            self.empty_label = None
        else:
            self.empty_label = empty_label

        # bypassing ChoiceField constructor, see ModelChoiceField implementation for reference
        Field.__init__(self,
                       required=required,
                       label=label,
                       initial=initial,
                       **kwargs)
        self.widget.choices = self.choices
Пример #2
0
    def __init__(self,
                 querysets,
                 empty_label=_("Send to everyone"),
                 required=True,
                 widget=None,
                 label=None,
                 initial=None,
                 help_text="",
                 limit_choices_to=None,
                 **kwargs):
        if required and (initial is not None):
            self.empty_label = None
        else:
            self.empty_label = empty_label

        # Call Field instead of ChoiceField __init__() because we don't need
        # ChoiceField.__init__().
        Field.__init__(self,
                       required=required,
                       widget=widget,
                       label=label,
                       initial=initial,
                       help_text=help_text,
                       **kwargs)

        self._querysets = querysets
Пример #3
0
    def __init__(
        self,
        *,
        payment_modes=None,
        empty_label=_("Choisissez votre moyen de paiement"),
        required=True,
        initial=None,
        label=_("Mode de paiement"),
        **kwargs
    ):

        if payment_modes == "ALL":
            self._payment_modes = settings.PAYMENT_MODES
        elif payment_modes is None:
            self._payment_modes = [PAYMENT_MODES["system_pay"], PAYMENT_MODES["check"]]
        else:
            self._payment_modes = payment_modes

        if required:
            self.empty_label = None
        else:
            self.empty_label = empty_label

        # bypassing ChoiceField constructor, see ModelChoiceField implementation for reference
        Field.__init__(self, required=required, label=label, initial=initial, **kwargs)
        self.widget.choices = self.choices
Пример #4
0
class PersonForm(BaseNestedModelForm):
    RESOLVE = (
        ("", "-------"),
        ("IGNORE", "Ignore"),
        ("USE", "Use Existing"),
    )

    check = BooleanField(required=False)
    resolve = Field(required=False, widget=HiddenInput())
    existing = Field(required=False, widget=HiddenInput())

    class Meta:
        model = Person

    def full_clean(self):
        self.cleaned_data = {}
        super(PersonForm, self).full_clean()
        check = self.cleaned_data.get("check", None)
        resolve = self.cleaned_data.get("resolve", None)
        existing = self.cleaned_data.get("existing", None)
        name = self.cleaned_data.get("name", None)
        surname = self.cleaned_data.get("surname", None)
        conflicting = Person.objects.filter(surname=surname).exclude(
            id=self.instance.id)
        if conflicting and (check or not self.instance.id):
            self.fields["resolve"] = ChoiceField(choices=PersonForm.RESOLVE,
                                                 required=False,
                                                 label="Resolve")
            self.fields["existing"] = ModelChoiceField(queryset=conflicting,
                                                       required=False,
                                                       label="Existing")
            msgs = [
                u"Conflicting Person:",
            ]
            for c in conflicting:
                msgs.append("%s %s" %
                            (": ".join(c.person_info()), c.identify()))
            if not resolve:
                # modify
                self._update_errors({
                    "resolve": ["Choose a way to resolve conflict!"],
                    NON_FIELD_ERRORS:
                    msgs,
                })
            elif resolve == "IGNORE":
                pass
            elif resolve == "USE":
                if not existing:
                    self._update_errors({
                        "existing": ["Choose an existing entry!"],
                        NON_FIELD_ERRORS:
                        msgs,
                    })
                else:
                    self.instance.id = existing
Пример #5
0
 def _get_field(self, field_name: T.Text, field: forms.Field) -> interact.PromptLoop:
     label = self._make_label(field_name, field.label)
     while True:
         value = yield self._input_for_field(label, field)
         try:
             field.clean(value)
         except forms.ValidationError as e:
             for error in walk_errors(e):
                 yield interact.Error(message=error)
         else:
             return value
Пример #6
0
class WorkerForm(ModelForm):
    date_in = Field(widget=DateInputWidget, label=_('date in'))
    date_out = Field(widget=DateInputWidget, label=_('date out'))

    class Meta:
        model = Worker
        exclude = ('company',)

    def __init__(self, *args, **kwargs):
        super(WorkerForm, self).__init__(*args, **kwargs)
        _instance = kwargs.pop('instance', None)
        add_form_control_class(self.fields)
        self.fields['date_out'].required = False
Пример #7
0
class ContactForm(Form):
    locale = CharField(required=False)
    persone = Field(required=True)
    organisation = Field(required=False)

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)

    def clean(self):
        super(ContactForm, self).clean()
        data = self.cleaned_data
        if 'persone' in data:
            P_F = PersoneForm(data['persone'])
            if P_F.is_valid():
                pass
            else:
                if 'address' in P_F.errors:
                    self.add_error('persone', P_F.errors['address'])
                self.add_error('persone', str(Error(P_F.errors)))
            if data['organisation'] != None:
                O_F = OrganisationForm(data['organisation'])
                if O_F.is_valid():
                    pass
                else:
                    self.add_error('organisation', str(Error(O_F.errors)))
        else:
            self.add_error('persone', str(Error(['persone'])))

    def save(self):
        contact_record = Contact()
        contact_record.save()
        if 'address' in self.data['persone']:
            address_data = self.data['persone'].pop('address')
            address_record = Address(**address_data)
        else:
            address_record = Address()
        address_record.save()
        self.data['persone']['address'] = address_record
        self.data['persone']['contact'] = contact_record
        persone_record = Person(**self.data['persone']).save()
        if 'organisation' in self.data:
            self.data['organisation']['contact'] == contact_record
            address_data = self.data['organisation'].pop('address')
            address_record = Address(**address_data)
            address_record.save()
            self.data['organisation']['address'] = address_record
            organisation_record = Organisation(**self.data['organisation'])
            organisation_record.save()
        return contact_record
Пример #8
0
class OrganisationForm(Form):
    name = Field(required=True)
    address = Field(required=True)

    def __init__(self, *args, **kwargs):
        super(OrganisationForm, self).__init__(*args, **kwargs)

    def clean(self):
        super(OrganisationForm, self).clean()
        data = self.cleaned_data
        A_F = AddressForm(data['address'])
        if A_F.is_valid():
            pass
        else:
            self.add_error('address', str(Error(A_F.errors)))
Пример #9
0
 def formfield_for_dbfield(self, db_field, request, obj=None, **kwargs):
     field = super().formfield_for_dbfield(db_field, request, **kwargs)
     if db_field.name == "payment":
         return Field(
             widget=PaymentWidget(obj=obj), initial=field.initial, required=False
         )
     return field
Пример #10
0
class ProposalForm(AjaxModelForm):
    description = CharField(widget=MarkItUpWidget())
    need = CharField(widget=HiddenInput())
    contacts = CharField(required=False, widget=ContactsWidget())
    tags = Field(
        widget=TaggitWidget(autocomplete_url="/proposal/search_tags/"),
        required=False)

    class Meta:
        model = Proposal
        fields = ('title', 'short_description', 'description', 'contacts',
                  'cost', 'need', 'tags')

    _field_labels = {
        'title': _('Title'),
        'description': _('Description'),
        'short_description': _('Short description'),
        'contacts': _('Contacts'),
        'tags': _('Tags'),
        'cost': _('Cost'),
        'need': ' '
    }

    def __init__(self, *a, **kw):
        # Crispy forms configuration
        self.helper = MooHelper(form_id="proposal_form")
        return super(ProposalForm, self).__init__(*a, **kw)

    @notify_on_update
    def save(self, *a, **kw):
        return super(ProposalForm, self).save(*a, **kw)

    def clean_need(self):
        return clean_autocomplete_field(self.cleaned_data['need'], Need)
Пример #11
0
 def get_form(self, form_class=None):
     form = SectionBasedConfigurationForm(
         self.request.POST or None,
         initial={
             "sections":
             global_preferences_registry.manager()["beachguard__sections"]
         })
     form.fields = {"sections": Field(widget=HiddenInput, required=False)}
     return form
Пример #12
0
def bind_subform(*, subform: 'TypeSubform', field: Field):
    """Initializes field attributes thus linking them to a subform.

    :param subform:
    :param field:

    """
    field.widget.form = subform
    field.form = subform
Пример #13
0
 def formfield_for_dbfield(self, db_field, request, **kwargs):
     """Customise the formfields of event and member"""
     field = super().formfield_for_dbfield(db_field, request, **kwargs)
     if db_field.name in ("event", "member"):
         # Disable add/change/delete buttons
         field.widget.can_add_related = False
         field.widget.can_change_related = False
         field.widget.can_delete_related = False
     elif db_field.name == "payment":
         return Field(widget=PaymentWidget, initial=field.initial, required=False)
     return field
Пример #14
0
class PersoneForm(Form):
    firstName = CharField(max_length=150, required=True)
    lastName = CharField(max_length=150, required=True)
    email = EmailField(max_length=254, required=True)
    address = Field(required=False)

    def __init__(self, *args, **kwargs):
        super(PersoneForm, self).__init__(*args, **kwargs)

    def clean(self):
        super(PersoneForm, self).clean()
        data = self.cleaned_data
        if data['address'] != None:
            A_F = AddressForm(data['address'])
            if A_F.is_valid():
                pass
            else:
                self.add_error('address', str(Error(A_F.errors)))
Пример #15
0
class ChapterForm(ModelForm):
    """ Форма добавления новой главы к рассказу """
    textarea_dict = {'class': 'input-xxlarge chapter-textarea'}
    attrs_dict = {'class': 'input-xxlarge'}
    # Название
    title = CharField(
        required=True,
        widget=TextInput(attrs=dict(
            attrs_dict, maxlength=512, placeholder='Заголовок новой главы')),
        label='Название',
        max_length=512,
        error_messages={
            'required': 'Пожалуйста, назовите новую главу вашего рассказа'
        },
    )
    # Текст главы'
    text = CharField(
        widget=Textarea(
            attrs=dict(textarea_dict, placeholder='Текст новой главы')),
        label='Текст главы',
        required=False,
    )
    # Заметки к главе
    notes = CharField(
        required=False,
        widget=Textarea(attrs=dict(attrs_dict,
                                   rows=4,
                                   cols=10,
                                   maxlength=4096,
                                   placeholder='Заметки к главе')),
        max_length=4096,
        label='Заметки',
        help_text='Заметки автора к главе',
    )
    # Кнопка "Отправить"
    button_submit = Field(
        required=False,
        widget=ServiceButtonWidget(attrs={'class': 'btn btn-primary'}),
    )

    # Метакласс
    class Meta:
        model = Chapter
        fields = ('title', 'text', 'notes')
Пример #16
0
 def test_field_sets_widget_is_required(self):
     self.assertTrue(Field(required=True).widget.is_required)
     self.assertFalse(Field(required=False).widget.is_required)
Пример #17
0
 def test_disabled_field_has_changed_always_false(self):
     disabled_field = Field(disabled=True)
     self.assertFalse(disabled_field.has_changed("x", "y"))
Пример #18
0
class MergeEntitiesBaseForm(CremeForm):
    entities_labels = Field(label='',
                            required=False,
                            widget=EntitiesHeaderWidget)

    class CanNotMergeError(Exception):
        pass

    def __init__(self, entity1, entity2, *args, **kwargs):
        # super(MergeEntitiesBaseForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.entity1 = entity1
        self.entity2 = entity2

        user = self.user
        fields = self.fields

        build_initial = self._build_initial_dict
        entity1_initial = build_initial(entity1)
        entity2_initial = build_initial(entity2)

        # The older entity is preferred
        initial_index = 0 if entity1.modified <= entity2.modified else 1

        for name, field in fields.items():
            if name == 'entities_labels':
                field.initial = (str(entity1), str(entity2),
                                 _(u'Merged entity'))
            else:
                initial = [entity1_initial[name], entity2_initial[name]]
                # We try to initialize with preferred one, but we use the other if it is empty.
                initial.append(initial[initial_index]
                               or initial[1 - initial_index])
                field.initial = initial

        # Custom fields --------------------------------------------------------
        # TODO: factorise (CremeEntityForm ? get_custom_fields_n_values ? ...)
        cfields = CustomField.objects.filter(content_type=entity1.entity_type)
        CremeEntity.populate_custom_values([entity1, entity2], cfields)
        self._customs = customs = [(
            cfield,
            entity1.get_custom_value(cfield),
            entity2.get_custom_value(cfield),
        ) for cfield in cfields]

        for i, (cfield, cvalue1, cvalue2) in enumerate(customs):
            formfield1 = cfield.get_formfield(cvalue1)
            # fields[_CUSTOM_NAME % i] = merge_field = MergeField(formfield1,
            fields[_CUSTOM_NAME.format(i)] = merge_field = MergeField(
                formfield1,
                model_field=None,
                label=cfield.name,
                user=user,
            )

            initial = [
                formfield1.initial,
                cfield.get_formfield(cvalue2).initial,
            ]
            initial.append(initial[initial_index]
                           or initial[1 - initial_index])
            merge_field.initial = initial

    def _build_initial_dict(self, entity):
        return model_to_dict(entity)

    def _post_entity1_update(self, entity1, entity2, cleaned_data):
        for i, (custom_field, cvalue1, cvalue2) in enumerate(self._customs):
            # value = cleaned_data[_CUSTOM_NAME % i]
            value = cleaned_data[_CUSTOM_NAME.format(
                i)]  # TODO: factorize with __init__() ?
            CustomFieldValue.save_values_for_entities(custom_field, [entity1],
                                                      value)

            if cvalue2 is not None:
                cvalue2.delete()

    def clean(self):
        # cdata = super(MergeEntitiesBaseForm, self).clean()
        cdata = super().clean()

        if not self._errors:
            entity1 = self.entity1

            for name in self.fields:
                try:
                    mfield = entity1._meta.get_field(name)
                except FieldDoesNotExist:
                    pass
                else:
                    if not getattr(mfield, 'many_to_many', False):
                        setattr(entity1, name, cdata[name])

            entity1.full_clean()

        return cdata

    @atomic
    def save(self, *args, **kwargs):
        # super(MergeEntitiesBaseForm, self).save(*args, **kwargs)
        super().save(*args, **kwargs)
        cdata = self.cleaned_data

        entity1 = self.entity1
        entity2 = self.entity2

        entity1.save()
        self._post_entity1_update(entity1, entity2, cdata)
        pre_merge_related.send_robust(sender=entity1, other_entity=entity2)

        replace_related_object(entity2, entity1)

        # ManyToManyFields
        for m2m_field in entity1._meta.many_to_many:
            name = m2m_field.name
            m2m_data = cdata.get(name)
            if m2m_data is not None:
                getattr(entity1, name).set(m2m_data)

        try:
            entity2.delete()
        except Exception as e:
            logger.error(
                'Error when merging 2 entities : the old one "%s"(id=%s) cannot be deleted: %s',
                entity2, entity2.id, e)
Пример #19
0
 def validate(self, value):
     return Field.validate(self, value)
Пример #20
0
 def build_type_textfield(self, field):
     return Field(label=field.name)
Пример #21
0
class ParametersForm(Form):
    """Parameters forms."""

    parameters = Field(label='Paramaters', required=False, initial={})
    input = Field(label='Input', required=False, initial={})

    def __init__(self, data=None, script=None, node=None):
        if script is not None:
            assert node is not None, "node must be passed with script!"
            data = {
                'parameters': script.parameters,
                'input': data,
            }
        else:
            data = {'parameters': data}
        super().__init__(data=data)
        self._node = node
        self._script = script

    def clean_parameters(self):
        """Validate the parameters set in the embedded YAML within the script.
        """
        parameters = self.data.get('parameters')
        if not isinstance(parameters, dict):
            set_form_error(self, "parameters", "Must be a dictionary")
            return

        for param, fields in parameters.items():
            # All parameter values should have a type defined.
            # Only currently supported parameter types are storage and runtime.
            param_type = fields.get('type')
            param_min = fields.get('min')
            param_max = fields.get('max')
            param_title = fields.get('title')
            param_description = fields.get('description')
            param_argument_format = fields.get('argument_format')
            param_default = fields.get('default')
            param_required = fields.get('required', True)

            # Check param data type.
            if not isinstance(param, str):
                set_form_error(self, "parameters",
                               "%s: parameter must be a string" % param)
            # Check fields data types.
            if not isinstance(param_type, str):
                set_form_error(self, "parameters",
                               "%s: type must be a string" % param_type)
            if param_min is not None and not isinstance(param_min, int):
                set_form_error(self, "parameters",
                               "%s: min must be an integer" % param_min)
            if param_max is not None and not isinstance(param_max, int):
                set_form_error(self, "parameters",
                               "%s: max must be an integer" % param_max)
            if param_title is not None and not isinstance(param_title, str):
                set_form_error(self, "parameters",
                               "%s: title must be a string" % param_title)
            if param_description is not None and not isinstance(
                    param_description, str):
                set_form_error(
                    self, "parameters",
                    "%s: description must be a string" % param_description)
            if param_argument_format is not None and not isinstance(
                    param_argument_format, str):
                set_form_error(
                    self, "parameters",
                    "%s: argument_format must be a string" %
                    param_argument_format)
            if param_default is not None and not isinstance(
                    param_default, str):
                set_form_error(self, "parameters",
                               "%s: default must be a string" % param_default)
            if param_required is not None and not isinstance(
                    param_required, bool):
                set_form_error(
                    self, "parameters",
                    "%s: required must be a boolean" % param_required)

            # Check parameter type is supported and required.
            if param_type not in ('storage', 'runtime') and param_required:
                set_form_error(
                    self, "parameters",
                    "%s: type must be either storage or runtime" % param_type)
            if param_type == 'storage' and (param_min is not None
                                            or param_max is not None):
                set_form_error(self, "parameters",
                               "storage type doesn't support min or max")
            if param_type == 'runtime' and isinstance(param_min, int):
                if param_min < 0:
                    set_form_error(
                        self, "parameters",
                        "runtime minimum must be greater than zero")
            if isinstance(param_min, int) and isinstance(param_max, int):
                if param_min > param_max:
                    set_form_error(self, "parameters",
                                   "min must be less than max")
            if isinstance(param_argument_format, str):
                if param_type == 'storage':
                    if not any(format in param_argument_format
                               for format in ('{input}', '{name}', '{path}',
                                              '{model}', '{serial}')):
                        set_form_error(
                            self, "parameters",
                            "%s: argument_format must contain one of {input}, "
                            "{name}, {path}, {model}, {serial}" % param_type)
                else:
                    if '{input}' not in param_argument_format:
                        set_form_error(
                            self, "parameters",
                            "%s: argument_format must contain {input}" %
                            param_type)

        return parameters

    def _setup_input(self):
        """Split input result and multi_result categories and set defaults.

        The users may specify multiple storage devices for the storage
        parameter. This results in one ScriptResult per storage device to allow
        each storage device to have its own logs and results. Each ScriptResult
        needs to include values for all parameters. The two lists will be
        combined later so each ScriptResult has a complete set of parameters.

        Any parameter which was not defined will have its default value set,
        if available.
        """
        parameters = self.data.get('parameters', {})
        input = self.data.get('input', {})

        if not isinstance(input, dict):
            set_form_error(self, 'input', 'Input must be a dictionary')
            return {}, {}

        # Paramaters which map to a single ScriptResult
        result_params = {}
        # Paramaters which may require multiple ScriptResults(storage)
        multi_result_params = {}

        # Split user input into params which need one ScriptResult per
        # param and one which may need multiple ScriptResults per param.
        for param_name, value in input.items():
            if param_name not in parameters:
                set_form_error(
                    self, 'input', "Unknown parameter '%s' for %s" %
                    (param_name, self._script.name))
                continue
            if parameters[param_name]['type'] == 'storage':
                multi_result_params[param_name] = copy.deepcopy(
                    parameters[param_name])
                multi_result_params[param_name]['value'] = value
            else:
                result_params[param_name] = copy.deepcopy(
                    parameters[param_name])
                result_params[param_name]['value'] = value

        # Check for any paramaters not given which have defaults.
        for param_name, param in parameters.items():
            if (param['type'] == 'storage'
                    and param_name not in multi_result_params):
                default = param.get('default', 'all')
                if not default and param.get('required', True):
                    set_form_error(self, param_name, 'Field is required')
                elif default:
                    multi_result_params[param_name] = copy.deepcopy(param)
                    multi_result_params[param_name]['value'] = default
            elif (param['type'] == 'runtime'
                  and param_name not in result_params):
                default = param.get('default', self._script.timeout.seconds)
                if (not isinstance(default, int)
                        and param.get('required', True)):
                    set_form_error(self, param_name, 'Field is required')
                elif isinstance(default, int):
                    result_params[param_name] = copy.deepcopy(param)
                    result_params[param_name]['value'] = default

        return result_params, multi_result_params

    def _validate_and_clean_runtime(self, param_name, param):
        """Validate and clean runtime input."""
        value = param['value']
        min_value = param.get('min', 0)
        max_value = param.get('max')
        if isinstance(value, str) and value.isdigit():
            value = int(value)
        if not isinstance(value, int):
            set_form_error(self, param_name, 'Must be an int')
            return
        if value < min_value:
            set_form_error(self, param_name,
                           "Must be greater than %s" % min_value)
        if max_value is not None and value > max_value:
            set_form_error(self, param_name,
                           "Must be less than %s" % max_value)

    def _blockdevice_to_dict(self, block_device):
        """Convert a block device to a dictionary with limited fields."""
        return {
            'name': block_device.name,
            'id_path': block_device.id_path,
            'model': block_device.model,
            'serial': block_device.serial,
            'physical_blockdevice': block_device,
        }

    def _validate_and_clean_storage_all(self, param_name, param, result_params,
                                        ret):
        """Validate and clean storage input when set to all."""
        if not self._node.physicalblockdevice_set.exists():
            # Use 'all' as a place holder until the disks get added during
            # commissioning.
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = param
            ret.append(clean_param)
        else:
            for bd in self._node.physicalblockdevice_set:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._blockdevice_to_dict(
                    bd)
                ret.append(clean_param)

    def _validate_and_clean_storage_id(self, param_name, param, result_params,
                                       ret):
        """Validate and clean storage input when id."""
        try:
            bd = self._node.physicalblockdevice_set.get(id=int(param['value']))
        except ObjectDoesNotExist:
            set_form_error(self, param_name,
                           'Physical block id does not exist')
        else:
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = copy.deepcopy(param)
            clean_param[param_name]['value'] = self._blockdevice_to_dict(bd)
            ret.append(clean_param)

    def _validate_and_clean_storage(self, param_name, param, result_params,
                                    ret):
        """Validate and clean storage input."""
        value = param['value']
        for i in value.split(','):
            if ':' in i:
                # Allow users to specify a disk using the model and serial.
                model, serial = i.split(':')
                try:
                    bd = self._node.physicalblockdevice_set.get(model=model,
                                                                serial=serial)
                except ObjectDoesNotExist:
                    pass
                else:
                    clean_param = copy.deepcopy(result_params)
                    clean_param[param_name] = copy.deepcopy(param)
                    clean_param[param_name][
                        'value'] = self._blockdevice_to_dict(bd)
                    ret.append(clean_param)
                    continue

            qs = self._node.physicalblockdevice_set.filter(
                Q(name=i) | Q(name=os.path.basename(i)) | Q(model=i)
                | Q(serial=i) | Q(tags__overlap=[i]))
            if not qs.exists():
                set_form_error(
                    self, param_name, "Unknown storage device for %s(%s)" %
                    (self._node.fqdn, self._node.system_id))
                continue
            for bd in qs:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._blockdevice_to_dict(
                    bd)
                ret.append(clean_param)

    def clean_input(self):
        """Validate and clean parameter input.

        Validate that input is correct per the parameter description. Storage
        input will be transformed into a dictionary representing the selected
        storage device from the PhysicalBlockDevice type.

        input will be cleaned to be a list of parameter dicts. Each item in the
        list represents one set of parameters for the script. This allows each
        storage device to be run seperately.
        """
        ret = []
        # Only validating the parameter description, not input. Do nothing.
        if None in (self._script, self._node):
            return ret

        result_params, multi_result_params = self._setup_input()

        # Validate input for single ScriptResult params
        for param_name, param in result_params.items():
            if param['type'] == 'runtime':
                self._validate_and_clean_runtime(param_name, param)

        # Validate input for multi ScriptResult params
        for param_name, param in multi_result_params.items():
            value = param['value']
            if param['type'] == 'storage':
                if value == 'all':
                    self._validate_and_clean_storage_all(
                        param_name, param, result_params, ret)
                elif isinstance(value, int) or value.isdigit():
                    self._validate_and_clean_storage_id(
                        param_name, param, result_params, ret)
                else:
                    self._validate_and_clean_storage(param_name, param,
                                                     result_params, ret)

        if ret == []:
            return [result_params]
        else:
            return ret
Пример #22
0
 def test_disabled_field_has_changed_always_false(self):
     disabled_field = Field(disabled=True)
     self.assertFalse(disabled_field.has_changed('x', 'y'))
Пример #23
0
 def validate(self, value):
     return Field.validate(self, value)
Пример #24
0
class BGFinProdRegForm(Form):
    issuer_full_name = CharField(required=False)
    issuer_short_name = CharField(required=False)
    issuer_legal_address = CharField(required=False)

    issuer_ogrn = CharField(required=False)
    issuer_inn = CharField(required=False)
    issuer_kpp = CharField(required=False)

    tender_gos_number = CharField(required=False)
    tender_placement_type = CharField(required=False)
    tender_exec_law = ChoiceField(
        required=False,
        choices=[
            (consts.TENDER_EXEC_LAW_44_FZ, '44-ФЗ'),
            (consts.TENDER_EXEC_LAW_223_FZ, '223-ФЗ'),
            (consts.TENDER_EXEC_LAW_185_FZ, '185-ФЗ'),
            (consts.TENDER_EXEC_LAW_COMMERCIAL, 'Коммерческий'),
            (consts.TENDER_EXEC_LAW_CUSTOMS, 'Таможенная'),
            (consts.TENDER_EXEC_LAW_VAT, 'Возврат НДС'),
        ])
    tender_publish_date = DateField(required=False)
    tender_start_cost = DecimalField(decimal_places=2,
                                     required=False,
                                     localize=True)
    tender_final_cost = DecimalField(decimal_places=2,
                                     required=False,
                                     localize=True)

    tender_responsible_full_name = CharField(required=False)
    tender_responsible_legal_address = CharField(required=False)
    tender_responsible_inn = CharField(required=False)
    tender_responsible_kpp = CharField(required=False)
    tender_responsible_ogrn = CharField(required=False)

    bg_commercial_contract_subject = CharField(required=False)
    bg_commercial_contract_place_of_work = CharField(required=False)
    bg_commercial_contract_sum = DecimalField(decimal_places=2,
                                              required=False,
                                              localize=True)
    bg_commercial_contract_sign_date = DateField(required=False)
    bg_commercial_contract_end_date = DateField(required=False)

    balance_code_2400_offset_1 = BalanceCodeDecimalField(decimal_places=2,
                                                         required=False,
                                                         localize=True)
    balance_code_2400_offset_0 = BalanceCodeDecimalField(decimal_places=2,
                                                         required=False,
                                                         localize=True)

    bg_sum = DecimalForcedThousandsGroupedField(decimal_places=2,
                                                required=False,
                                                localize=True)
    bg_currency = ChoiceField(required=False,
                              choices=[
                                  (consts.CURRENCY_RUR, 'Рубль'),
                                  (consts.CURRENCY_USD, 'Доллар'),
                                  (consts.CURRENCY_EUR, 'Евро'),
                              ])
    bg_start_date = DateField(required=False)
    bg_end_date = DateField(required=False)
    bg_deadline_date = DateField(required=False)
    bg_type = ChoiceField(
        required=False,
        choices=[
            (consts.BG_TYPE_APPLICATION_ENSURE, 'Обеспечение заявки'),
            (consts.BG_TYPE_CONTRACT_EXECUTION, 'Исполнение контракта'),
            (consts.BG_TYPE_REFUND_OF_ADVANCE, 'Возврат аванса'),
            (consts.BG_TYPE_WARRANTY_ENSURE,
             'Обеспечение гарантийных обязательств'),
        ])
    bg_is_benefeciary_form = BooleanField(required=False,
                                          widget=Select(
                                              attrs={'class': 'form-control'},
                                              choices=[
                                                  (True, 'Да'),
                                                  (False, 'Нет'),
                                              ]))

    is_indisputable_charge_off = BooleanField(
        required=False,
        initial=True,
        widget=Select(attrs={'class': 'form-control'}))

    tender_contract_type = ChoiceField(
        required=False,
        choices=[
            (consts.TENDER_CONTRACT_TYPE_SUPPLY_CONTRACT, 'Поставка товара'),
            (consts.TENDER_CONTRACT_TYPE_SERVICE_CONTRACT, 'Оказание услуг'),
            (consts.TENDER_CONTRACT_TYPE_WORKS_CONTRACT, 'Выполнение работ'),
        ])
    tender_contract_subject = CharField(widget=Textarea(), required=False)
    stop_factors = Field(required=False)
    tender_has_prepayment = BooleanField(required=False)
    already_has_an_agent = Field(required=False)

    def clean(self):
        bg_sum_min = BankMinimalCommission.objects.order_by(
            'sum_min').first().sum_min
        bg_sum_max = BankMinimalCommission.objects.order_by(
            '-sum_max').first().sum_max
        if not self.cleaned_data[
                'bg_sum'] or not bg_sum_min < self.cleaned_data[
                    'bg_sum'] < bg_sum_max:
            self.add_error(None, 'Неверная сумма запрашиваемой гарантии')

        bg_start = self.cleaned_data['bg_start_date']
        bg_end = self.cleaned_data['bg_end_date']
        if bg_end and bg_start:
            bg_months_diff = 1 + (bg_end.year - bg_start.year
                                  ) * 12 + bg_end.month - bg_start.month
        else:
            bg_months_diff = 0
        if not bg_start or not bg_end or not 0 < bg_months_diff < 30:
            self.add_error(None,
                           'Неверный срок действия запрашиваемой гарантии')

        balance_code_2400_offset_0 = self.cleaned_data[
            'balance_code_2400_offset_0']
        balance_code_2400_offset_1 = self.cleaned_data[
            'balance_code_2400_offset_1']
        if balance_code_2400_offset_0 < 0 or balance_code_2400_offset_1 < 0:
            self.add_error(None, 'Отрицательная прибыль')
Пример #25
0
 def build_type_integerfield(self, field):
     return Field(label=field.name)
Пример #26
0
class StoryForm(ModelForm):
    attrs_dict = {'class': 'input-xxlarge'}
    img_attrs = {
        'group_container_class': 'characters-group group-',
        'data_attrs': {
            'class': 'hidden'
        },
        'container_attrs': {
            'class': 'character-item'
        }
    }
    radio_attrs = {
        'btn_attrs': {
            'type': 'button',
            'class': 'btn'
        },
        'data_attrs': {
            'class': 'hidden'
        },
        'btn_container_attrs': {
            'class': 'btn-group buttons-visible',
            'data-toggle': 'buttons-radio'
        },
        'data_container_attrs': {
            'class': 'buttons-data'
        },
    }
    checkbox_attrs = {
        'btn_attrs': {
            'type': 'button',
            'class': 'btn'
        },
        'data_attrs': {
            'class': 'hidden'
        },
        'btn_container_attrs': {
            'class': 'btn-group buttons-visible',
            'data-toggle': 'buttons-checkbox'
        },
        'data_container_attrs': {
            'class': 'buttons-data'
        },
    }
    # Персонажи
    characters = GroupedModelChoiceField(
        required=False,
        queryset=Character.objects.all(),
        group_by_field='group',
        widget=StoriesImgSelect(attrs=img_attrs),
        label='Персонажи',
        help_text=
        'Следует выбрать персонажей, находящихся в гуще событий, а не всех пони, упомянутых в произведении.',
    )
    # Жанры
    categories = ModelMultipleChoiceField(
        required=True,
        queryset=Category.objects.all(),
        widget=StoriesCheckboxSelectMultiple(
            attrs={
                'label_attrs': ['checkbox', 'inline', 'gen'],
                'label_id_related_attr': 'gen-'
            }),
        label='Жанры',
        help_text='Выберите жанр вашего рассказа',
        error_messages={'required': 'Жанры - обязательное поле'})
    # События
    classifications = ModelMultipleChoiceField(
        required=False,
        queryset=Classifier.objects.all(),
        widget=StoriesCheckboxSelectMultiple(
            attrs={'label_attrs': ['checkbox', 'inline']}),
        label='События',
        help_text='Ключевые события рассказа',
    )
    # Закончен/не закончен
    finished = ChoiceField(
        required=True,
        choices=[(0, 'Не закончен'), (1, 'Закончен')],
        widget=StoriesRadioButtons(attrs=radio_attrs),
        label='Статус',
        help_text='Завершен ли рассказ',
        error_messages={
            'required': 'Нужно обязательно указать статус рассказа!'
        },
    )
    # Заморожен/активен
    freezed = ChoiceField(
        required=True,
        choices=[(0, 'Активен'), (1, 'Заморожен')],
        widget=StoriesRadioButtons(attrs=radio_attrs),
        label='Состояние',
        help_text='Активность рассказа (пишется ли он сейчас)',
        error_messages={
            'required': 'Нужно обязательно указать состояние рассказа!'
        },
    )
    # Оригинал/перевод
    original = ChoiceField(
        required=True,
        choices=[(1, 'Оригинал'), (0, 'Перевод')],
        widget=StoriesRadioButtons(attrs=radio_attrs),
        label='Происхождение',
        error_messages={
            'required': 'Нужно обязательно указать происхождение рассказа!'
        },
    )
    # Рейтинг
    rating = ModelChoiceField(
        required=True,
        empty_label=None,
        queryset=Rating.objects.order_by('-id'),
        widget=StoriesRadioButtons(attrs=radio_attrs),
        label='Рейтинг',
        error_messages={
            'required': 'Нужно обязательно указать рейтинг рассказа!'
        },
    )
    # Краткое описание рассказа
    summary = CharField(
        required=True,
        widget=Textarea(
            attrs=dict(attrs_dict,
                       maxlength=4096,
                       placeholder='Обязательное краткое описание рассказа')),
        max_length=4096,
        label='Краткое описание рассказа',
        error_messages={
            'required':
            'Опишите вкратце содержание рассказа - это обязательное поле'
        },
    )
    # Заметки к рассказу
    notes = CharField(
        required=False,
        widget=Textarea(attrs=dict(
            attrs_dict, maxlength=4096, placeholder='Заметки к рассказу')),
        max_length=4096,
        label='Заметки',
    )
    # Название
    title = CharField(
        required=True,
        widget=TextInput(attrs=dict(attrs_dict,
                                    maxlength=512,
                                    placeholder='Заголовок нового рассказа')),
        label='Название',
        max_length=512,
        error_messages={'required': 'Пожалуйста, назовите ваш рассказ'},
    )
    # Кнопка "Сохранить"
    button_submit = Field(
        required=False,
        widget=ServiceButtonWidget(attrs={'class': 'btn btn-primary'}),
        initial='Сохранить')

    # Метакласс
    class Meta:
        model = Story
        fields = ('characters', 'categories', 'classifications', 'finished',
                  'freezed', 'original', 'rating', 'summary', 'notes', 'title')
Пример #27
0
class ReservationForm(BaseNestedModelForm):
    RESOLVE = (
        ("", "-------"),
        ("FORCE", "Force save"),
        ("SWAP", "Swap Appartments"),
    )

    resolve = Field(label="Resolve", required=False, widget=HiddenInput())
    period = ModelChoiceField(queryset=Period.objects.all(),
                              required=False,
                              label="Period")

    def __init__(self, *args, **kwargs):
        super(ReservationForm, self).__init__(*args, **kwargs)
        self.fields[
            "owner"].queryset = MilitaryPerson.objects.prefetch_related(
                "rank").all().order_by("surname", "name")

    class Meta:
        model = Reservation
        fields = [
            "res_type", "agent", "period", "check_in", "check_out", "owner",
            "appartment", "status", "persons", "book_ref", "telephone"
        ]

    def clean(self):
        super(ReservationForm, self).clean()

        def get_datetime(value):
            if value:
                y, m, d = map(int, value.split("-"))
                return datetime.date(y, m, d)

        period = self.cleaned_data.get("period", None)
        check_in = self.cleaned_data.get("check_in", None)
        check_out = self.cleaned_data.get("check_out", None)
        if period and (check_in or check_out):
            self._update_errors({
                "period": ["You must provide either period or dates!"],
            })
        if period:
            self.cleaned_data["check_in"] = period.start
            self.cleaned_data["check_out"] = period.end
        return self.cleaned_data

    def full_clean(self):
        self.cleaned_data = {}
        super(ReservationForm, self).full_clean()
        if self.instance.appartment:
            reservations = self.instance.appartment.reservations.filter(
                status__in=[RS_PENDING, RS_CONFIRM, RS_UNKNOWN]).exclude(
                    id=self.instance.id)
            conflicting = []
            for r in reservations:
                if (self.instance.status
                        in (RS_PENDING, RS_CONFIRM, RS_UNKNOWN)
                        and r.owner.id != self.instance.owner.id and r.inside(
                            self.instance.check_in, self.instance.check_out)):
                    conflicting.append(r)
            if conflicting:
                self.fields["resolve"] = ChoiceField(
                    choices=ReservationForm.RESOLVE,
                    required=False,
                    label="Resolve")
                resolve = self.cleaned_data.get("resolve", None)
                print "resolving...."
                msgs = [
                    u"Conflicting Reservations:",
                ]
                if not resolve:
                    self._update_errors({
                        "resolve": ["Choose a way to resolve conflict!"],
                        NON_FIELD_ERRORS:
                        msgs + [r.info for r in conflicting],
                    })
                if resolve == "FORCE":
                    pass
                if resolve == "SWAP":
                    if len(conflicting) > 1:
                        self._update_errors({
                            "resolve":
                            ["Swap is not supported for many conflicts!"],
                            NON_FIELD_ERRORS:
                            msgs + [r.info for r in conflicting],
                        })
                    else:
                        # TODO: find first available appartment
                        appartment = None
                        if self.instance.id:
                            existing = Reservation.objects.get(
                                id=self.instance.id)
                            appartment = existing.appartment
                        conflicting[0].appartment = appartment
                        conflicting[0].save()
                msg = (
                    u"Conflicting Reservations:\n%s\nRESOLVE: %s\nChanged: %s\nNew/Updated: %s"
                    % ("\n".join([c.info for c in conflicting]), resolve,
                       conflicting[0].info, self.instance.info))
                print msg.encode("utf-8")
Пример #28
0
 def validate(self, value):
     if value == '-':
         return '-'
     return Field.validate(self, value)
Пример #29
0
class ParametersForm(Form):
    """Parameters forms."""

    parameters = Field(label="Paramaters", required=False, initial={})
    input = Field(label="Input", required=False, initial={})

    def __init__(self, data=None, script=None, node=None):
        if script is not None:
            assert node is not None, "node must be passed with script!"
            data = {"parameters": script.parameters, "input": data}
        else:
            data = {"parameters": data}
        super().__init__(data=data)
        self._node = node
        self._script = script

    def _get_interfaces(self, *args, **kwargs):
        """Return a list of configured interfaces."""
        ifaces = [
            interface
            for interface in self._node.interface_set.filter(
                children_relationships=None, enabled=True, *args, **kwargs
            ).prefetch_related("ip_addresses")
            if interface.is_configured()
        ]
        if (
            not ifaces
            and self._node.status == NODE_STATUS.COMMISSIONING
            and self._node.boot_interface
        ):
            # During commissioning no interface will have a configured IP
            # address if network information wasn't kept. The netplan
            # configuration will use DHCP on the boot_interface. Allow it
            # to be selected for a ScriptResult during commissioning so
            # regeneration works.
            ifaces = [self._node.boot_interface]
        return ifaces

    def clean_parameters(self):
        """Validate the parameters set in the embedded YAML within the script."""
        parameters = self.data.get("parameters")
        if not isinstance(parameters, dict):
            set_form_error(self, "parameters", "Must be a dictionary")
            return

        for param, fields in parameters.items():
            # All parameter values should have a type defined.
            # Only currently supported parameter types are storage and runtime.
            param_type = fields.get("type")
            param_min = fields.get("min")
            param_max = fields.get("max")
            param_title = fields.get("title")
            param_description = fields.get("description")
            param_argument_format = fields.get("argument_format")
            param_default = fields.get("default")
            param_required = fields.get("required", True)
            allow_list = fields.get("allow_list")
            choices = fields.get("choices")

            # Check param data type.
            if not isinstance(param, str):
                set_form_error(
                    self,
                    "parameters",
                    "%s: parameter must be a string" % param,
                )
            # Check fields data types.
            if not isinstance(param_type, str):
                set_form_error(
                    self,
                    "parameters",
                    "%s: type must be a string" % param_type,
                )
            if param_min is not None and not isinstance(param_min, int):
                set_form_error(
                    self,
                    "parameters",
                    "%s: min must be an integer" % param_min,
                )
            if param_max is not None and not isinstance(param_max, int):
                set_form_error(
                    self,
                    "parameters",
                    "%s: max must be an integer" % param_max,
                )
            if param_title is not None and not isinstance(param_title, str):
                set_form_error(
                    self,
                    "parameters",
                    "%s: title must be a string" % param_title,
                )
            if param_description is not None and not isinstance(
                param_description, str
            ):
                set_form_error(
                    self,
                    "parameters",
                    "%s: description must be a string" % param_description,
                )
            if param_argument_format is not None and not isinstance(
                param_argument_format, str
            ):
                set_form_error(
                    self,
                    "parameters",
                    "%s: argument_format must be a string"
                    % param_argument_format,
                )
            if param_default is not None and not isinstance(
                param_default, str
            ):
                set_form_error(
                    self,
                    "parameters",
                    "%s: default must be a string" % param_default,
                )
            if param_required is not None and not isinstance(
                param_required, bool
            ):
                set_form_error(
                    self,
                    "parameters",
                    "%s: required must be a boolean" % param_required,
                )
            if allow_list is not None and not isinstance(allow_list, bool):
                set_form_error(
                    self,
                    "parameters",
                    "%s: allow_list must be a boolean" % allow_list,
                )
            if allow_list is not None and param_type != "url":
                set_form_error(
                    self,
                    "parameters",
                    "allow_list only supported with the url type.",
                )
            if choices is not None:
                if not isinstance(choices, list):
                    set_form_error(
                        self,
                        "parameters",
                        "choices must be a list",
                    )
                else:
                    for choice in choices:
                        if isinstance(choice, list) and not isinstance(
                            choice, str
                        ):
                            if (
                                len(choice) != 2
                                or (not isinstance(choice[0], str))
                                or (not isinstance(choice[1], str))
                            ):
                                set_form_error(
                                    self,
                                    "parameters",
                                    "choice must be a Django choice or string",
                                )
            if choices is not None and param_type != "choice":
                set_form_error(
                    self,
                    "parameters",
                    "choices only supported with the choice type.",
                )
            if param_type == "choice" and not choices:
                set_form_error(
                    self,
                    "parameters",
                    'choices must be given with a "choice" parameter type!',
                )

            # Check parameter type is supported and required.
            if (
                param_type
                not in (
                    "storage",
                    "interface",
                    "url",
                    "runtime",
                    "string",
                    "password",
                    "choice",
                )
                and param_required
            ):
                set_form_error(
                    self,
                    "parameters",
                    "%s: type must be either storage, interface, url, "
                    "runtime, string, password, or choice" % param_type,
                )
            if param_type in ("storage", "interface", "url", "choice") and (
                param_min is not None or param_max is not None
            ):
                set_form_error(
                    self, "parameters", "Type doesn't support min or max"
                )
            if param_type == "runtime" and isinstance(param_min, int):
                if param_min < 0:
                    set_form_error(
                        self,
                        "parameters",
                        "runtime minimum must be greater than zero",
                    )
            if isinstance(param_min, int) and isinstance(param_max, int):
                if param_min > param_max:
                    set_form_error(
                        self, "parameters", "min must be less than max"
                    )
            if isinstance(param_argument_format, str):
                if param_type == "storage":
                    if not any(
                        format in param_argument_format
                        for format in (
                            "{input}",
                            "{name}",
                            "{path}",
                            "{model}",
                            "{serial}",
                        )
                    ):
                        set_form_error(
                            self,
                            "parameters",
                            "%s: argument_format must contain one of {input}, "
                            "{name}, {path}, {model}, {serial}" % param_type,
                        )
                elif param_type == "interface":
                    if not any(
                        format in param_argument_format
                        for format in (
                            "{input}",
                            "{name}",
                            "{mac}",
                            "{vendor}",
                            "{product}",
                        )
                    ):
                        set_form_error(
                            self,
                            "parameters",
                            "%s: argument_format must contain one of {input}, "
                            "{name}, {mac}, {vendor}, {product}" % param_type,
                        )
                else:
                    if "{input}" not in param_argument_format:
                        set_form_error(
                            self,
                            "parameters",
                            "%s: argument_format must contain {input}"
                            % param_type,
                        )

        return parameters

    def _setup_input(self):
        """Split input result and multi_result categories and set defaults.

        Users may specify multiple devices for the storage and interface
        parameters. This results in one ScriptResult per device to allow each
        each device to have its own logs and results. Each ScriptResult
        needs to include values for all parameters. The two lists will be
        combined later so each ScriptResult has a complete set of parameters.

        Any parameter which was not defined will have its default value set,
        if available.
        """
        parameters = self.data.get("parameters", {})
        input = self.data.get("input", {})

        if not isinstance(input, dict):
            set_form_error(self, "input", "Input must be a dictionary")
            return {}, {}

        # Paramaters which map to a single ScriptResult
        result_params = {}
        # Paramaters which may require multiple ScriptResults(storage)
        multi_result_params = {}

        default_from_maas_config = DEFAULTS_FROM_MAAS_CONFIG.union(
            input.keys()
        )
        default_defaults = (
            Config.objects.get_configs(default_from_maas_config)
            if default_from_maas_config
            else {}
        )

        # Split user input into params which need one ScriptResult per
        # param and one which may need multiple ScriptResults per param.
        for param_name, value in input.items():
            if param_name not in parameters:
                set_form_error(
                    self,
                    "input",
                    "Unknown parameter '%s' for %s"
                    % (param_name, self._script.name),
                )
                continue
            if parameters[param_name]["type"] in ("storage", "interface"):
                multi_result_params[param_name] = copy.deepcopy(
                    parameters[param_name]
                )
                multi_result_params[param_name]["value"] = value
            else:
                result_params[param_name] = copy.deepcopy(
                    parameters[param_name]
                )
                result_params[param_name]["value"] = value

        # Check for any paramaters not given which have defaults.
        for param_name, param in parameters.items():
            if (
                param["type"] in ("storage", "interface")
                and param_name not in multi_result_params
            ):
                default = param.get("default", "all")
                if not default and param.get("required", True):
                    set_form_error(self, param_name, "Field is required")
                elif default:
                    multi_result_params[param_name] = copy.deepcopy(param)
                    multi_result_params[param_name]["value"] = default
            elif param_name not in result_params:
                if param["type"] == "runtime":
                    default = param.get(
                        "default", self._script.timeout.seconds
                    )
                    if not isinstance(default, int) and param.get(
                        "required", True
                    ):
                        set_form_error(self, param_name, "Field is required")
                    elif isinstance(default, int):
                        result_params[param_name] = copy.deepcopy(param)
                        result_params[param_name]["value"] = default
                else:
                    default = param.get(
                        "default", default_defaults.get(param_name, "")
                    )
                    if not default and param.get("required", False):
                        set_form_error(self, param_name, "Field is required")
                    elif default:
                        result_params[param_name] = copy.deepcopy(param)
                        result_params[param_name]["value"] = default

        return result_params, multi_result_params

    def _validate_and_clean_runtime(self, param_name, param):
        """Validate and clean runtime input."""
        value = param["value"]
        min_value = param.get("min", 0)
        max_value = param.get("max")
        if isinstance(value, str) and value.isdigit():
            value = int(value)
        if not isinstance(value, int):
            set_form_error(self, param_name, "Must be an int")
            return
        if value < min_value:
            set_form_error(
                self, param_name, "Must be greater than %s" % min_value
            )
        if max_value is not None and value > max_value:
            set_form_error(
                self, param_name, "Must be less than %s" % max_value
            )

    def _blockdevice_to_dict(self, block_device):
        """Convert a block device to a dictionary with limited fields."""
        return {
            "name": block_device.name,
            "id_path": block_device.id_path,
            "model": block_device.model,
            "serial": block_device.serial,
            "physical_blockdevice": block_device,
        }

    def _validate_and_clean_storage_all(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean storage input when set to all."""
        if len(self._node.physicalblockdevice_set) == 0:
            # Use 'all' as a place holder until the disks get added during
            # commissioning.
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = param
            ret.append(clean_param)
        else:
            for bd in self._node.physicalblockdevice_set:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]["value"] = self._blockdevice_to_dict(
                    bd
                )
                ret.append(clean_param)

    def _validate_and_clean_storage_id(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean storage input when id."""
        try:
            bd = self._node.physicalblockdevice_set.get(id=int(param["value"]))
        except ObjectDoesNotExist:
            set_form_error(
                self, param_name, "Physical block id does not exist"
            )
        else:
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = copy.deepcopy(param)
            clean_param[param_name]["value"] = self._blockdevice_to_dict(bd)
            ret.append(clean_param)

    def _validate_and_clean_storage(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean storage input."""
        value = param["value"]
        for i in value.split(","):
            if ":" in i:
                # Allow users to specify a disk using the model and serial.
                model, serial = i.split(":")
                try:
                    bd = self._node.physicalblockdevice_set.get(
                        model=model, serial=serial
                    )
                except ObjectDoesNotExist:
                    pass
                else:
                    clean_param = copy.deepcopy(result_params)
                    clean_param[param_name] = copy.deepcopy(param)
                    clean_param[param_name][
                        "value"
                    ] = self._blockdevice_to_dict(bd)
                    ret.append(clean_param)
                    continue

            qs = self._node.physicalblockdevice_set.filter(
                Q(name=i)
                | Q(name=os.path.basename(i))
                | Q(model=i)
                | Q(serial=i)
                | Q(tags__overlap=[i])
            )
            if len(qs) == 0:
                set_form_error(
                    self,
                    param_name,
                    "Unknown storage device for %s(%s)"
                    % (self._node.fqdn, self._node.system_id),
                )
                continue
            for bd in qs:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]["value"] = self._blockdevice_to_dict(
                    bd
                )
                ret.append(clean_param)

    def _interface_to_dict(self, interface):
        """Convert an interface to a dictionary with limited fields."""
        return {
            "name": interface.name,
            "mac_address": str(interface.mac_address),
            "vendor": interface.vendor,
            "product": interface.product,
            "interface": interface,
        }

    def _validate_and_clean_interface_all(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean interface input when set to all."""
        interfaces = self._get_interfaces()
        if len(interfaces) == 0:
            # Use 'all' as a place holder until the Interfaces get added during
            # commissioning.
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = param
            ret.append(clean_param)
        else:
            for interface in interfaces:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]["value"] = self._interface_to_dict(
                    interface
                )
                ret.append(clean_param)

    def _validate_and_clean_interface_id(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean interface input when id."""
        interfaces = self._get_interfaces(id=int(param["value"]))
        if len(interfaces) != 1:
            set_form_error(self, param_name, "Interface id does not exist")
        else:
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = copy.deepcopy(param)
            clean_param[param_name]["value"] = self._interface_to_dict(
                interfaces[0]
            )
            ret.append(clean_param)

    def _validate_and_clean_interface(
        self, param_name, param, result_params, ret
    ):
        """Validate and clean interface input."""
        value = param["value"]
        for i in value.split(","):
            if ":" in i:
                # Allow users to specify an Interface using the vendor and
                # product.
                vendor, product = i.split(":")
                interfaces = self._get_interfaces(
                    vendor=vendor, product=product
                )
                if len(interfaces) != 0:
                    for interface in interfaces:
                        clean_param = copy.deepcopy(result_params)
                        clean_param[param_name] = copy.deepcopy(param)
                        clean_param[param_name][
                            "value"
                        ] = self._interface_to_dict(interface)
                        ret.append(clean_param)
                    continue

            if is_mac(i):
                interfaces = self._get_interfaces(mac_address=i)
            else:
                interfaces = self._get_interfaces(
                    Q(name=i)
                    | Q(vendor=i)
                    | Q(product=i)
                    | Q(tags__overlap=[i])
                )
            if len(interfaces) == 0:
                set_form_error(
                    self,
                    param_name,
                    "Unknown interface for %s(%s)"
                    % (self._node.fqdn, self._node.system_id),
                )
                continue
            for interface in interfaces:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]["value"] = self._interface_to_dict(
                    interface
                )
                ret.append(clean_param)

    def _validate_and_clean_url(self, param_name, param):
        """Validate and clean URL input."""
        if param.get("allow_list", False):
            value = param["value"].split(",")
        else:
            value = [param["value"]]

        for url in value:
            # Django's validator requires a protocol but we accept just a
            # hostname or IP address.
            try:
                ip = ip_address(url)
            except ValueError:
                if "://" not in url:
                    url = "http://%s" % url
            else:
                if ip.version == 4:
                    url = "http://%s" % url
                else:
                    url = "http://[%s]" % url
            # Allow all schemes supported by curl(used with the network
            # validation test) + icmp.
            try:
                validate_url(
                    url,
                    schemes=[
                        "icmp",
                        "file",
                        "ftp",
                        "ftps",
                        "gopher",
                        "http",
                        "https",
                        "imap",
                        "imaps",
                        "ldap",
                        "ldaps",
                        "pop3",
                        "pop3s",
                        "rtmp",
                        "rtsp",
                        "scp",
                        "sftp",
                        "smb",
                        "smbs",
                        "smtp",
                        "smtps",
                        "telnet",
                        "tftp",
                    ],
                )
            except ValidationError:
                set_form_error(self, param_name, "Invalid URL")

    def _validate_and_clean_string(self, param_name, param):
        """Validate and clean string and password input."""
        if "min" in param and len(param["value"]) < param["min"]:
            set_form_error(self, param_name, "Input too short")
        if "max" in param and len(param["value"]) > param["max"]:
            set_form_error(self, param_name, "Input too long")

    def _validate_and_clean_choices(self, param_name, param):
        # Support a Django choice list or a string list
        choices = [
            choice if isinstance(choice, str) else choice[0]
            for choice in param["choices"]
        ]
        if param["value"] not in choices:
            set_form_error(
                self, param_name, f"Invalid choice \"{param['value']}\""
            )

    def clean_input(self):
        """Validate and clean parameter input.

        Validate that input is correct per the parameter description. Storage
        input will be transformed into a dictionary representing the selected
        storage device from the PhysicalBlockDevice type.

        input will be cleaned to be a list of parameter dicts. Each item in the
        list represents one set of parameters for the script. This allows each
        storage device to be run seperately.
        """
        ret = []
        # Only validating the parameter description, not input. Do nothing.
        if None in (self._script, self._node):
            return ret

        result_params, multi_result_params = self._setup_input()

        # Validate input for single ScriptResult params
        for param_name, param in result_params.items():
            if param["type"] == "runtime":
                self._validate_and_clean_runtime(param_name, param)
            elif param["type"] == "url":
                self._validate_and_clean_url(param_name, param)
            elif param["type"] in ["string", "password"]:
                self._validate_and_clean_string(param_name, param)
            elif param["type"] == "choice":
                self._validate_and_clean_choices(param_name, param)

        # Validate input for multi ScriptResult params
        for param_name, param in multi_result_params.items():
            value = param["value"]
            if param["type"] == "storage":
                if value == "all":
                    self._validate_and_clean_storage_all(
                        param_name, param, result_params, ret
                    )
                elif isinstance(value, int) or value.isdigit():
                    self._validate_and_clean_storage_id(
                        param_name, param, result_params, ret
                    )
                else:
                    self._validate_and_clean_storage(
                        param_name, param, result_params, ret
                    )
            elif param["type"] == "interface":
                if value == "all":
                    self._validate_and_clean_interface_all(
                        param_name, param, result_params, ret
                    )
                elif isinstance(value, int) or value.isdigit():
                    self._validate_and_clean_interface_id(
                        param_name, param, result_params, ret
                    )
                else:
                    self._validate_and_clean_interface(
                        param_name, param, result_params, ret
                    )

        if ret == []:
            return [result_params]
        else:
            return ret
Пример #30
0
class ParametersForm(Form):
    """Parameters forms."""

    parameters = Field(label='Paramaters', required=False, initial={})
    input = Field(label='Input', required=False, initial={})

    def __init__(self, data=None, script=None, node=None):
        if script is not None:
            assert node is not None, "node must be passed with script!"
            data = {
                'parameters': script.parameters,
                'input': data,
            }
        else:
            data = {'parameters': data}
        super().__init__(data=data)
        self._node = node
        self._script = script

    def _get_interfaces(self):
        """Return a queryset of the Interfaces that can be used."""
        interfaces = self._node.interface_set.filter(
            children_relationships=None,
            enabled=True)
        interfaces = interfaces.exclude(
            ip_addresses__alloc_type=IPADDRESS_TYPE.DISCOVERED)
        # Exclude all IPAddresses of type DISCOVERED before checking if an
        # Interface doesn't have IPAddresses. If done as one excludes
        # DISCOVERED IPAddresses won't be filtered out before isnull is
        # checked.
        return interfaces.exclude(
            ip_addresses__isnull=True, ip_addresses__ip=None)

    def clean_parameters(self):
        """Validate the parameters set in the embedded YAML within the script.
        """
        parameters = self.data.get('parameters')
        if not isinstance(parameters, dict):
            set_form_error(self, "parameters", "Must be a dictionary")
            return

        for param, fields in parameters.items():
            # All parameter values should have a type defined.
            # Only currently supported parameter types are storage and runtime.
            param_type = fields.get('type')
            param_min = fields.get('min')
            param_max = fields.get('max')
            param_title = fields.get('title')
            param_description = fields.get('description')
            param_argument_format = fields.get('argument_format')
            param_default = fields.get('default')
            param_required = fields.get('required', True)
            allow_list = fields.get('allow_list')

            # Check param data type.
            if not isinstance(param, str):
                set_form_error(
                    self, "parameters",
                    "%s: parameter must be a string" % param)
            # Check fields data types.
            if not isinstance(param_type, str):
                set_form_error(
                    self, "parameters",
                    "%s: type must be a string" % param_type)
            if param_min is not None and not isinstance(param_min, int):
                set_form_error(
                    self, "parameters",
                    "%s: min must be an integer" % param_min)
            if param_max is not None and not isinstance(param_max, int):
                set_form_error(
                    self, "parameters",
                    "%s: max must be an integer" % param_max)
            if param_title is not None and not isinstance(param_title, str):
                set_form_error(
                    self, "parameters",
                    "%s: title must be a string" % param_title)
            if param_description is not None and not isinstance(
                    param_description, str):
                set_form_error(
                    self, "parameters",
                    "%s: description must be a string" % param_description)
            if param_argument_format is not None and not isinstance(
                    param_argument_format, str):
                set_form_error(
                    self, "parameters",
                    "%s: argument_format must be a string"
                    % param_argument_format)
            if param_default is not None and not isinstance(
                    param_default, str):
                set_form_error(
                    self, "parameters",
                    "%s: default must be a string" % param_default)
            if param_required is not None and not isinstance(
                    param_required, bool):
                set_form_error(
                    self, "parameters",
                    "%s: required must be a boolean" % param_required)
            if allow_list is not None and not isinstance(allow_list, bool):
                set_form_error(
                    self, "parameters",
                    "%s: allow_list must be a boolean" % allow_list)
            if allow_list is not None and param_type != 'url':
                set_form_error(
                    self, "parameters",
                    "allow_list only supported with the url type.")

            # Check parameter type is supported and required.
            if (param_type not in (
                    'storage', 'interface', 'url', 'runtime') and
                    param_required):
                set_form_error(
                    self, "parameters",
                    "%s: type must be either storage, interface, url, or "
                    "runtime" % param_type)
            if param_type in ('storage', 'interface', 'url') and (
                    param_min is not None or param_max is not None):
                set_form_error(
                    self, "parameters", "Type doesn't support min or max")
            if param_type == 'runtime' and isinstance(param_min, int):
                if param_min < 0:
                    set_form_error(
                        self, "parameters",
                        "runtime minimum must be greater than zero")
            if isinstance(param_min, int) and isinstance(param_max, int):
                if param_min > param_max:
                    set_form_error(
                        self, "parameters", "min must be less than max")
            if isinstance(param_argument_format, str):
                if param_type == 'storage':
                    if not any(
                            format in param_argument_format
                            for format in ('{input}', '{name}', '{path}',
                                           '{model}', '{serial}')):
                        set_form_error(
                            self, "parameters",
                            "%s: argument_format must contain one of {input}, "
                            "{name}, {path}, {model}, {serial}" % param_type)
                elif param_type == 'interface':
                    if not any(
                            format in param_argument_format
                            for format in ('{input}', '{name}', '{mac}',
                                           '{vendor}', '{product}')):
                        set_form_error(
                            self, "parameters",
                            "%s: argument_format must contain one of {input}, "
                            "{name}, {mac}, {vendor}, {product}" % param_type)
                else:
                    if '{input}' not in param_argument_format:
                        set_form_error(
                            self, "parameters",
                            "%s: argument_format must contain {input}"
                            % param_type)

        return parameters

    def _setup_input(self):
        """Split input result and multi_result categories and set defaults.

        Users may specify multiple devices for the storage and interface
        parameters. This results in one ScriptResult per device to allow each
        each device to have its own logs and results. Each ScriptResult
        needs to include values for all parameters. The two lists will be
        combined later so each ScriptResult has a complete set of parameters.

        Any parameter which was not defined will have its default value set,
        if available.
        """
        parameters = self.data.get('parameters', {})
        input = self.data.get('input', {})

        if not isinstance(input, dict):
            set_form_error(self, 'input', 'Input must be a dictionary')
            return {}, {}

        # Paramaters which map to a single ScriptResult
        result_params = {}
        # Paramaters which may require multiple ScriptResults(storage)
        multi_result_params = {}

        # Split user input into params which need one ScriptResult per
        # param and one which may need multiple ScriptResults per param.
        for param_name, value in input.items():
            if param_name not in parameters:
                set_form_error(
                    self, 'input', "Unknown parameter '%s' for %s" % (
                        param_name, self._script.name))
                continue
            if parameters[param_name]['type'] in ('storage', 'interface'):
                multi_result_params[param_name] = copy.deepcopy(
                    parameters[param_name])
                multi_result_params[param_name]['value'] = value
            else:
                result_params[param_name] = copy.deepcopy(
                    parameters[param_name])
                result_params[param_name]['value'] = value

        # Check for any paramaters not given which have defaults.
        for param_name, param in parameters.items():
            if (param['type'] in ('storage', 'interface') and
                    param_name not in multi_result_params):
                default = param.get('default', 'all')
                if not default and param.get('required', True):
                    set_form_error(self, param_name, 'Field is required')
                elif default:
                    multi_result_params[param_name] = copy.deepcopy(param)
                    multi_result_params[param_name]['value'] = default
            elif param_name not in result_params:
                if param['type'] == 'runtime':
                    default = param.get(
                        'default', self._script.timeout.seconds)
                    if (not isinstance(default, int) and
                            param.get('required', True)):
                        set_form_error(self, param_name, 'Field is required')
                    elif isinstance(default, int):
                        result_params[param_name] = copy.deepcopy(param)
                        result_params[param_name]['value'] = default
                else:
                    default = param.get('default', '')
                    if not default and param.get('required', False):
                        set_form_error(self, param_name, 'Field is required')
                    elif default:
                        result_params[param_name] = copy.deepcopy(param)
                        result_params[param_name]['value'] = default

        return result_params, multi_result_params

    def _validate_and_clean_runtime(self, param_name, param):
        """Validate and clean runtime input."""
        value = param['value']
        min_value = param.get('min', 0)
        max_value = param.get('max')
        if isinstance(value, str) and value.isdigit():
            value = int(value)
        if not isinstance(value, int):
            set_form_error(self, param_name, 'Must be an int')
            return
        if value < min_value:
            set_form_error(
                self, param_name, "Must be greater than %s" % min_value)
        if max_value is not None and value > max_value:
            set_form_error(
                self, param_name, "Must be less than %s" % max_value)

    def _blockdevice_to_dict(self, block_device):
        """Convert a block device to a dictionary with limited fields."""
        return {
            'name': block_device.name,
            'id_path': block_device.id_path,
            'model': block_device.model,
            'serial': block_device.serial,
            'physical_blockdevice': block_device,
        }

    def _validate_and_clean_storage_all(
            self, param_name, param, result_params, ret):
        """Validate and clean storage input when set to all."""
        if len(self._node.physicalblockdevice_set) == 0:
            # Use 'all' as a place holder until the disks get added during
            # commissioning.
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = param
            ret.append(clean_param)
        else:
            for bd in self._node.physicalblockdevice_set:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._blockdevice_to_dict(
                    bd)
                ret.append(clean_param)

    def _validate_and_clean_storage_id(
            self, param_name, param, result_params, ret):
        """Validate and clean storage input when id."""
        try:
            bd = self._node.physicalblockdevice_set.get(id=int(param['value']))
        except ObjectDoesNotExist:
            set_form_error(
                self, param_name, 'Physical block id does not exist')
        else:
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = copy.deepcopy(param)
            clean_param[param_name]['value'] = self._blockdevice_to_dict(bd)
            ret.append(clean_param)

    def _validate_and_clean_storage(
            self, param_name, param, result_params, ret):
        """Validate and clean storage input."""
        value = param['value']
        for i in value.split(','):
            if ':' in i:
                # Allow users to specify a disk using the model and serial.
                model, serial = i.split(':')
                try:
                    bd = self._node.physicalblockdevice_set.get(
                        model=model, serial=serial)
                except ObjectDoesNotExist:
                    pass
                else:
                    clean_param = copy.deepcopy(result_params)
                    clean_param[param_name] = copy.deepcopy(param)
                    clean_param[param_name][
                        'value'] = self._blockdevice_to_dict(bd)
                    ret.append(clean_param)
                    continue

            qs = self._node.physicalblockdevice_set.filter(
                Q(name=i) | Q(name=os.path.basename(i)) |
                Q(model=i) | Q(serial=i) | Q(tags__overlap=[i]))
            if len(qs) == 0:
                set_form_error(
                    self, param_name, "Unknown storage device for %s(%s)" % (
                        self._node.fqdn, self._node.system_id))
                continue
            for bd in qs:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._blockdevice_to_dict(
                    bd)
                ret.append(clean_param)

    def _interface_to_dict(self, interface):
        """Convert an interface to a dictionary with limited fields."""
        return {
            'name': interface.name,
            'mac_address': str(interface.mac_address),
            'vendor': interface.vendor,
            'product': interface.product,
            'interface': interface,
        }

    def _validate_and_clean_interface_all(
            self, param_name, param, result_params, ret):
        """Validate and clean interface input when set to all."""
        interfaces = self._get_interfaces()
        if len(interfaces) == 0:
            # Use 'all' as a place holder until the Interfaces get added during
            # commissioning.
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = param
            ret.append(clean_param)
        else:
            for interface in interfaces:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._interface_to_dict(
                    interface)
                ret.append(clean_param)

    def _validate_and_clean_interface_id(
            self, param_name, param, result_params, ret):
        """Validate and clean interface input when id."""
        try:
            interface = self._get_interfaces().get(id=int(param['value']))
        except ObjectDoesNotExist:
            set_form_error(
                self, param_name, 'Interface id does not exist')
        else:
            clean_param = copy.deepcopy(result_params)
            clean_param[param_name] = copy.deepcopy(param)
            clean_param[param_name]['value'] = self._interface_to_dict(
                interface)
            ret.append(clean_param)

    def _validate_and_clean_interface(
            self, param_name, param, result_params, ret):
        """Validate and clean interface input."""
        value = param['value']
        for i in value.split(','):
            if ':' in i:
                # Allow users to specify an Interface using the vendor and
                # product.
                vendor, product = i.split(':')
                try:
                    interface = self._get_interfaces().get(
                        vendor=vendor, product=product)
                except ObjectDoesNotExist:
                    pass
                else:
                    clean_param = copy.deepcopy(result_params)
                    clean_param[param_name] = copy.deepcopy(param)
                    clean_param[param_name]['value'] = self._interface_to_dict(
                        interface)
                    ret.append(clean_param)
                    continue

            if is_mac(i):
                qs = self._get_interfaces().filter(mac_address=i)
            else:
                qs = self._get_interfaces().filter(
                    Q(name=i) | Q(vendor=i) | Q(product=i) |
                    Q(tags__overlap=[i]))
            if len(qs) == 0:
                set_form_error(
                    self, param_name, "Unknown interface for %s(%s)" % (
                        self._node.fqdn, self._node.system_id))
                continue
            for interface in qs:
                clean_param = copy.deepcopy(result_params)
                clean_param[param_name] = copy.deepcopy(param)
                clean_param[param_name]['value'] = self._interface_to_dict(
                    interface)
                ret.append(clean_param)

    def _validate_and_clean_url(self, param_name, param):
        """Validate and clean URL input."""
        if param.get('allow_list', False):
            value = param['value'].split(',')
        else:
            value = [param['value']]

        for url in value:
            # Django's validator requires a protocol but we accept just a
            # hostname or IP address.
            try:
                ip = ip_address(url)
            except ValueError:
                if '://' not in url:
                    url = 'http://%s' % url
            else:
                if ip.version == 4:
                    url = 'http://%s' % url
                else:
                    url = 'http://[%s]' % url
            # Allow all schemes supported by curl(used with the network
            # validation test) + icmp.
            try:
                validate_url(url, schemes=[
                    'icmp', 'file', 'ftp', 'ftps', 'gopher', 'http', 'https',
                    'imap', 'imaps', 'ldap', 'ldaps', 'pop3', 'pop3s', 'rtmp',
                    'rtsp', 'scp', 'sftp', 'smb', 'smbs', 'smtp', 'smtps',
                    'telnet', 'tftp'])
            except ValidationError:
                set_form_error(self, param_name, 'Invalid URL')

    def clean_input(self):
        """Validate and clean parameter input.

        Validate that input is correct per the parameter description. Storage
        input will be transformed into a dictionary representing the selected
        storage device from the PhysicalBlockDevice type.

        input will be cleaned to be a list of parameter dicts. Each item in the
        list represents one set of parameters for the script. This allows each
        storage device to be run seperately.
        """
        ret = []
        # Only validating the parameter description, not input. Do nothing.
        if None in (self._script, self._node):
            return ret

        result_params, multi_result_params = self._setup_input()

        # Validate input for single ScriptResult params
        for param_name, param in result_params.items():
            if param['type'] == 'runtime':
                self._validate_and_clean_runtime(param_name, param)
            elif param['type'] == 'url':
                self._validate_and_clean_url(param_name, param)

        # Validate input for multi ScriptResult params
        for param_name, param in multi_result_params.items():
            value = param['value']
            if param['type'] == 'storage':
                if value == 'all':
                    self._validate_and_clean_storage_all(
                        param_name, param, result_params, ret)
                elif isinstance(value, int) or value.isdigit():
                    self._validate_and_clean_storage_id(
                        param_name, param, result_params, ret)
                else:
                    self._validate_and_clean_storage(
                        param_name, param, result_params, ret)
            elif param['type'] == 'interface':
                if value == 'all':
                    self._validate_and_clean_interface_all(
                        param_name, param, result_params, ret)
                elif isinstance(value, int) or value.isdigit():
                    self._validate_and_clean_interface_id(
                        param_name, param, result_params, ret)
                else:
                    self._validate_and_clean_interface(
                        param_name, param, result_params, ret)

        if ret == []:
            return [result_params]
        else:
            return ret
Пример #31
0
 def clean(self, value):
     value = self.to_python(value)
     return Field.clean(self,value)
Пример #32
0
 def get_form(self, form_class=None):
     form = super().get_form(form_class)
     form.fields[self.operation_mark_field] = Field(initial=self.operation, widget=HiddenInput)
     if self.csrf_token_for_form is not None:
         form.fields['csrfmiddlewaretoken'] = Field(initial=self.csrf_token_for_form, widget=HiddenInput)
     return form
Пример #33
0
 def validate(self, value):
     if value == '-':
         return '-'
     return Field.validate(self, value)
Пример #34
0
class SearchForm(Form):
    checkbox_attrs = {
        'btn_attrs': {'type': 'button', 'class': 'btn'},
        'data_attrs': {'class': 'hidden'},
        'btn_container_attrs': {'class': 'btn-group buttons-visible', 'data-toggle': 'buttons-checkbox'},
        'data_container_attrs': {'class': 'buttons-data'},
    }
    radio_attrs = {
        'btn_attrs': {'type': 'button', 'class': 'btn'},
        'data_attrs': {'class': 'hidden'},
        'btn_container_attrs': {'class': 'btn-group buttons-visible', 'data-toggle': 'buttons-radio'},
        'data_container_attrs': {'class': 'buttons-data'},
    }
    img_attrs = {
        'group_container_class': 'characters-group group-',
        'data_attrs': {'class': 'hidden'},
        'container_attrs': {'class': 'character-item'}
    }
    # Строка поиска
    search_query = CharField(
        required=False,
        widget=TextInput(
            attrs={
                'size': 32,
                'placeholder': 'Пинки-поиск',
                'id': 'appendedInputButtons',
                'class': 'span3',
                'maxlength': 128,
            }
        ),
        max_length=128,
    )
    # Минимальный размер
    search_min_size = IntegerField(
        required=False,
        widget=NumberInput(
            attrs={
                'size': 8,
                'placeholder': 'От',
                'class': 'span3',
                'maxlength': 8,
                'min': 0,
                'max': 99999000,
                'step': 1000,
            }
        ),
    )
    # Максимальный размер
    search_max_size = IntegerField(
        required=False,
        widget=NumberInput(
            attrs={
                'size': 8,
                'placeholder': 'До',
                'class': 'span3',
                'maxlength': 8,
                'min': 0,
                'max': 99999000,
                'step': 1000,
            }
        ),
    )
    # Жанры
    categories_select = ModelMultipleChoiceField(
        queryset=Category.objects.all(),
        required=False,
        widget=StoriesCheckboxSelectMultiple(
            attrs={
                'label_attrs': ['checkbox', 'inline', 'gen'],
                'label_id_related_attr': 'gen-',
            },
        ),
    )
    # Персонажи
    characters_select = GroupedModelChoiceField(
        required=False,
        queryset=Character.objects.all(),
        group_by_field='group',
        widget=StoriesImgSelect(attrs=img_attrs),
    )
    # Оригинал/перевод
    originals_select = MultipleChoiceField(
        choices=[(0, 'Перевод'), (1, 'Оригинал')],
        required=False,
        widget=StoriesButtons(attrs=checkbox_attrs),
    )
    # Статус рассказа
    finished_select = MultipleChoiceField(
        choices=[(0, 'Не завершен'), (1, 'Завершен')],
        required=False,
        widget=StoriesButtons(attrs=checkbox_attrs),
    )
    # Активность рассказа
    freezed_select = MultipleChoiceField(
        choices=[(0, 'Активен'), (1, 'Заморожен')],
        required=False,
        widget=StoriesButtons(attrs=checkbox_attrs),
    )
    # Рейтинги
    ratings_select = ModelMultipleChoiceField(
        queryset=Rating.objects.all(),
        required=False,
        widget=StoriesButtons(attrs=checkbox_attrs),
    )
    # События
    classifications_select = ModelMultipleChoiceField(
        queryset=Classifier.objects.all(),
        required=False,
        widget=StoriesCheckboxSelectMultiple(attrs={'label_attrs': ['checkbox', 'inline']}),
    )
    # Кнопка "Развернуть тонкие настройки поиска"
    button_advanced = Field(
        required=False,
        widget=ButtonWidget(
            attrs={
                'type': 'button',
                'class': 'btn btn-collapse',
                'data-toggle': 'collapse',
                'data-target': '#more-info',
                'text': 'Еще более тонкий поиск'
            }
        ),
    )
    # Кнопка "Развернуть фильтры"
    button_filters = Field(
        required=False,
        widget=ButtonWidget(
            attrs={
                'type': 'button',
                'class': 'btn btn-collapse',
                'data-toggle': 'collapse',
                'data-target': '#more-filters',
                'text': 'Фильтры поиска'
            }
        ),
    )
    # Кнопка "Развернуть сортировку"
    button_sort = Field(
        required=False,
        widget=ButtonWidget(
            attrs={
                'type': 'button',
                'class': 'btn btn-collapse',
                'data-toggle': 'collapse',
                'data-target': '#more-sort',
                'text': 'Сортировка результатов'
            }
        ),
    )
    # Сортировка
    sort_type = MultipleChoiceField(
        choices=[(1, 'По дате'), (2, 'По размеру'), (3, 'По рейтингу'), (4, 'По комментам')],
        required=False,
        widget=StoriesButtons(attrs=checkbox_attrs),
    )
    # bla
    button_submit = Field(
        required=False,
        widget=ServiceButtonWidget(attrs={'class': 'btn btn-primary'}),
        initial='Искать!',
    )
    button_reset = Field(
        required=False,
        widget=StoriesServiceInput(
            attrs={
                'type': 'reset',
                'class': 'btn',
                'id': 'reset_search',
                'value': 'Очистить',
            }
        ),
    )
    # Тип поиска
    search_type = ChoiceField(
        choices=[(0, 'Быстрый'), (1, 'Полный')],
        required=True,
        widget=StoriesRadioButtons(attrs=radio_attrs),
    )