def customize(self, customizer):

        # customization is done in the form and in the template

        value_field_name = self.get_value_field_name()

        self.fields[value_field_name].help_text = customizer.documentation

        # you can customize the category of scientific properties,
        # so set it here...
        category_customizer = customizer.category
        self.initial["category_key"] = category_customizer.get_key()

        if customizer.field_type != "ENUMERATION":
            atomic_type = customizer.atomic_type
            if atomic_type:
                if atomic_type != MetadataAtomicFieldTypes.DEFAULT:
                    custom_widget_class = METADATA_ATOMICFIELD_MAP[atomic_type][0]
                    custom_widget_args = METADATA_ATOMICFIELD_MAP[atomic_type][1]
                    self.fields["atomic_value"].widget = custom_widget_class(**custom_widget_args)
                    # if I changed the widget, then I have to re-add the attributes that were updated in __init__ above
                    # b/c they will have been lost (I only have to do this for atomic fields b/c the widget for enumerations cannot change)
                    update_field_widget_attributes(self.fields["atomic_value"], {"onchange": "copy_value(this,'%s-scientific_property_value');" % self.prefix})
                    update_field_widget_attributes(self.fields["atomic_value"], {"class": "atomic_value changer"})

                update_field_widget_attributes(self.fields["atomic_value"], {"class": atomic_type.lower()})

        else:
            widget_attributes = {"class": "multiselect", }
            all_enumeration_choices = [(choice, choice) for choice in customizer.enumeration_choices]
            if customizer.enumeration_nullable:
                all_enumeration_choices += NULL_CHOICE
                widget_attributes["class"] += " nullable"
            if customizer.enumeration_open:
                all_enumeration_choices += OTHER_CHOICE
                widget_attributes["class"] += " open"
            if customizer.enumeration_multi:
                widget_attributes["class"] += " multiple"
                self.fields["enumeration_value"].set_choices(all_enumeration_choices, multi=True)
            else:
                widget_attributes["class"] += " single"
                # all_enumeration_choices = EMPTY_CHOICE + all_enumeration_choices
                self.fields["enumeration_value"].set_choices(all_enumeration_choices, multi=False)

            update_field_widget_attributes(self.fields["enumeration_value"], widget_attributes)
            update_field_widget_attributes(self.fields["enumeration_other_value"], {"class": "other"})

        # extra_attributes...
        if not customizer.edit_extra_standard_name:
            update_field_widget_attributes(self.fields["extra_standard_name"], {"class": "readonly", "readonly": "readonly"})

        if not customizer.edit_extra_description:
            update_field_widget_attributes(self.fields["extra_description"], {"class": "readonly", "readonly": "readonly"})

        if not customizer.edit_extra_units:
            update_field_widget_attributes(self.fields["extra_units"], {"class": "readonly", "readonly": "readonly"})

        set_field_widget_attributes(self.fields["extra_description"], {"cols": "60", "rows": "4"})

        self.customizer = customizer
    def __init__(self, *args, **kwargs):
        super(QPropertyCustomizationForm, self).__init__(*args, **kwargs)

        set_field_widget_attributes(self.fields["property_description"], {"rows": 2})
        set_field_widget_attributes(self.fields["cardinality"], {"readonly": True, "ng-disabled": "true"})
        update_field_widget_attributes(self.fields["cardinality"], {"class": "form-control-auto"})
        self.unbootstrap_fields(["inline_help", "is_required", "is_hidden", "is_editable", "is_nillable"])

        field_type = self.get_current_field_value("field_type")
        if field_type == QPropertyTypes.ATOMIC:
            update_field_widget_attributes(self.fields["atomic_type"], {"class": "select single show-tick"})
            set_field_widget_attributes(self.fields["atomic_suggestions"], {"rows": 2})
            set_field_widget_attributes(self.fields["default_values"], {"rows": 2})
        elif field_type == QPropertyTypes.ENUMERATION:
            set_field_widget_attributes(self.fields["default_values"], {"rows": 2})
            self.unbootstrap_fields(["enumeration_is_open"])
        elif field_type == QPropertyTypes.RELATIONSHIP:
            update_field_widget_attributes(self.fields["relationship_show_subforms"], {"readonly": True, "ng-disabled": "true"})
            update_field_widget_attributes(self.fields["relationship_is_hierarchical"], {"readonly": True, "ng-disabled": "true"})
            self.unbootstrap_fields(["relationship_show_subforms", "relationship_is_hierarchical"])
        else:
            msg = "Unknown field type: {0}".format(field_type)
            raise QError(msg)

        if self.instance.proxy.is_required:
            update_field_widget_attributes(self.fields["is_required"], {"readonly": True, "ng-disabled": "true"})

        if self.instance.has_specialized_values:
            update_field_widget_attributes(self.fields["default_values"], {"readonly": True, "ng-disabled": "true"})
            update_field_widget_attributes(self.fields["is_editable"], {"readonly": True, "ng-disabled": "true"})
 def __init__(self, *args, **kwargs):
     super(QCategoryCustomizationForm, self).__init__(*args, **kwargs)
     self.unbootstrap_field("is_hidden")
     update_field_widget_attributes(self.fields["category_title"], {"class": "form-control form-control-small"})
     update_field_widget_attributes(self.fields["category_description"], {"class": "form-control form-control-small"})
     set_field_widget_attributes(self.fields["category_description"], {"rows": 2})
     update_field_widget_attributes(self.fields["order"], {"ng-disabled": "true", "disabled": "disabled"})
def bootstrap_field(field):
    bootstrap_classes = {
        "class": "form-control",
    }
    update_field_widget_attributes(field, bootstrap_classes)
    if not isinstance(field, BooleanField):
        set_field_widget_attributes(field, {
            "placeholder": field.label,
        })
Exemple #5
0
    def __init__(self, *args, **kwargs):
        form_name = kwargs.get("form_name", None)
        assert form_name, "QForm must have a unique name."

        super(QForm, self).__init__(*args, **kwargs)
        # add the possibility of rendering a server error on _all_ fields
        for field_name, field in self.fields.items():
            set_field_widget_attributes(field, {
                "servererror": "true",
            })
Exemple #6
0
 def __init__(self, *args, **kwargs):
     super(QCategoryCustomizationForm, self).__init__(*args, **kwargs)
     if not self.instance.pk:
         # I don't need to reset the key b/c "get_new_customizations" passes it in via initial
         pass
     else:
         # TODO: DOUBLE-CHECK THAT I SHOULD SET ".initial[key]" and not ".fields[key].initial"
         # self.fields["key"].initial = self.instance.get_key()
         self.initial["key"] = self.instance.get_key()
     set_field_widget_attributes(self.fields["documentation"], {"rows": 2})
     update_field_widget_attributes(self.fields["order"], {"ng-disabled": "true"})
    def __init__(self, *args, **kwargs):

        super(QUserProfileForm, self).__init__(*args, **kwargs)

        profile = self.instance
        user = profile.user

        self.fields["first_name"].initial = user.first_name
        self.fields["last_name"].initial = user.last_name
        self.fields["email"].initial = user.email

        update_field_widget_attributes(self.fields["email"], {"readonly": True})
        set_field_widget_attributes(self.fields["description"], {"rows": 2})
        update_field_widget_attributes(self.fields["institute"], {"class": "select single show-tick"})
    def add_custom_potential_errors_to_field(self, field_name):

        form_field = self.fields[field_name]
        model_field = self.instance.get_field(field_name)

        # only check fields that have a correspondence to the model,
        # and that can be edited by the user...
        if model_field is not None and model_field.editable:

            custom_validators = [v for v in model_field.validators if isinstance(v, QValidator)]
            for validator in custom_validators:
                # this attribute is required for Angular to know about the custom validator
                set_field_widget_attributes(form_field, {validator.name: "true"})

            # and I store the validators for later use in get_field_errors() above
            setattr(form_field, "custom_potential_errors", custom_validators)
    def __init__(self, *args, **kwargs):
        super(QPropertyRealizationForm, self).__init__(*args, **kwargs)

        field_type = self.get_current_field_value("field_type")
        proxy = self.instance.proxy

        is_nil_field = self.fields["is_nil"]
        self.unbootstrap_field("is_nil")
        is_nil_field.help_text = mark_safe(
            _(
                "<p>Some properties can be intentionally left blank, provided there is a valid reason for doing so.</p>"
                "<p>Checking this box will reveal a drop-down menu allowing a reason to be specified.</p>"
                "<p>If a reason is specified, then any value on the left will be ignored during publication.</p>"
            )
        )

        if field_type == QPropertyTypes.ATOMIC:
            atomic_value_field = self.fields["atomic_value"]
            set_field_widget_attributes(atomic_value_field, {
                "ng-disabled": "current_model.is_nil"
            })

        elif field_type == QPropertyTypes.ENUMERATION:
            enumeration_value_field = self.fields["enumeration_value"]
            enumeration_other_field = self.fields["enumeration_other_value"]
            # TODO: "complete_choices", "is_multiple", etc. OUGHT TO HAVE BEEN SETUP IN "QPropertyRealization.__init__"
            # enumeration_value_field._complete_choices = proxy.enumeration_choices
            enumeration_value_field._is_multiple = proxy.is_multiple
            # just a one-off here: "enumeration_other_field" is not required on the model
            # but it is required if displayed in the form...
            custom_not_blank_validator = ValidateNotBlank()
            self.add_custom_form_validator_to_field(enumeration_other_field, custom_not_blank_validator)
            set_field_widget_attributes(enumeration_other_field, {
                "placeholder": ENUMERATION_OTHER_PLACEHOLDER,
                "ng-show": "value_in_array('{0}', current_model.enumeration_value)".format(ENUMERATION_OTHER_CHOICE),
                # angular validation wasn't running on blank fields
                # this prevented my "valildate_not_blank" fn from being called
                # turning off whitespace trimming solves this problem
                "ng-trim": "false"
            })

            set_field_widget_attributes(enumeration_value_field, {
                "ng-disabled": "current_model.is_nil"
            })
            set_field_widget_attributes(enumeration_other_field, {
                "ng-disabled": "current_model.is_nil"
            })

        else:  # field_type == QPropertyTypes.RELATIONSHIP:
            pass

        self.is_multiple = proxy.is_multiple
        # TODO: SHOULD THIS BE DEFERRED FROM DJANGO TO NG?  IT IS GUI LOGIC, BUT STILL THIS SEEMS KIND OF MESSY
        # TODO: (ONE REASON NOT TO MOVE IT TO NG IS THAT I WANT TO CHECK IF I SHOULD RENDER A CATEGORY/PROPERTY _BEFORE_ I DEFINE THE CORRESPONDING NG CONTROLLER)
        self.category_key = self.instance.category_key
        self.property_key = self.instance.key
    def __init__(self, *args, **kwargs):
        super(QScientificPropertyCustomizationForm, self).__init__(*args, **kwargs)

        is_new_property = not self.instance.pk
        proxy = self.get_proxy()
        field_type = self.get_field_type()

        if field_type == QPropertyTypes.ATOMIC:
            # things to do for ATOMIC fields...
            # TODO: THIS IS NO LONGER TRUE; "atomic_type" IS NOW A REQUIRED FIELD W/ A DEFAULT VALUE
            # # since atomic_fields only shows up if this is an ATOMIC field, it cannot be required
            # # but when I do display it, I can force users to make a choice
            # atomic_type_field = self.fields["atomic_type"]
            # atomic_type_field.required = True
            # atomic_type_field.empty_label = None
            # atomic_type_field.choices.remove(EMPTY_CHOICE[0])
            set_field_widget_attributes(self.fields["atomic_suggestions"], {"rows": 2})
            update_field_widget_attributes(self.fields["atomic_type"], {"class": "select single show-tick"})

        elif field_type == QPropertyTypes.ENUMERATION:
            # things to do for ENUMERATION fields...
            self.unbootstrap_fields(["enumeration_open", "enumeration_multi", "enumeration_nullable", ])
            choices = proxy.enumeration_choices.split('|')
            enumeration_choices_field = self.fields["enumeration_choices"]
            enumeration_default_field = self.fields["enumeration_default"]
            enumeration_choices_field.set_choices(choices)
            enumeration_default_field.set_choices(choices)
            update_field_widget_attributes(enumeration_choices_field, {"class": "select multiple show-tick"})
            update_field_widget_attributes(enumeration_default_field, {"class": "select multiple show-tick"})
            if is_new_property:
                self.initial["enumeration_choices"] = choices

        else:  # field_type == QPropertyTypes.RELATIONSHIP
            msg = "ScientificProperties cannot be RELATIONSHIPS"
            raise QError(msg)

        # things to do for ALL fields...

        # TODO: DOUBLE-CHECK THAT I SHOULD SET ".initial[key]" and not ".fields[key].initial"
        self.initial["key"] = self.instance.get_key()
        self.initial["category_key"] = self.instance.category.get_key()

        self.unbootstrap_fields(self._extra_fields + ["displayed", "required", "editable", "unique", "inline_help", ])
        set_field_widget_attributes(self.fields["documentation"], {"rows": 2})
Exemple #11
0
    def __init__(self, *args, **kwargs):
        super(QModelCustomizationForm, self).__init__(*args, **kwargs)

        # deal w/ customization_fields...
        self.unbootstrap_field("is_default")
        set_field_widget_attributes(self.fields["description"], {"rows": 2})

        # deal w/ document_fields...
        self.unbootstrap_field("model_show_all_categories")
        set_field_widget_attributes(self.fields["model_description"], {"rows": 2})

        # TODO: MAKE SURE THIS LINE IS NOT REPLICATED IN SUBFORMS
        update_field_widget_attributes(self.fields["name"], {
            # notice I'm using ng-blur instead of ng-change
            # ...this is much more efficient
            "ng-blur": "update_names({field_scope})".format(
                field_scope=self.get_qualified_model_field_name("name"),
            ),
        })
    def __init__(self, *args, **kwargs):
        super(QModelCustomizationForm, self).__init__(*args, **kwargs)

        # deal w/ customization_fields...
        self.unbootstrap_field("is_default")
        self.add_server_errors_to_field("name")
        self.add_server_errors_to_field("is_default")
        set_field_widget_attributes(self.fields["documentation"], {"rows": 2})

        # deal w/ document_fields...
        self.unbootstrap_field("model_show_empty_categories")
        set_field_widget_attributes(self.fields["model_description"], {"rows": 2})

        update_field_widget_attributes(self.fields["name"], {
            # notice I'm using ng-blur instead of ng-change
            # ...this is much more efficient
            "ng-blur": "update_names({field_scope})".format(
                field_scope=self.get_qualified_model_field_name("name"),
            ),
        })
    def add_custom_form_validator_to_field(self, form_field, custom_validator):
        """
        this is really similar to QForm.add_custom_potential_errors_to_field
        however, it doesn't assume that the validators come from the underlying model field
        instead it is used to explicitly customize which validators are fun on the form only
        (this is useful, for example, when customizing how to render ATOMIC fields)
        :param form_field:
        :param custom_validator:
        :return:
        """

        assert isinstance(custom_validator, QValidator), "{0} is an invalid validator".format(custom_validator)

        # add this validator to the set of existing errors (if it doesn't already exist)...
        custom_errors = getattr(form_field, "custom_potential_errors")
        if custom_validator.name in [e.name for e in custom_errors]:
            q_logger.error("{0} has already been added as a validator".format(custom_validator))
        else:
            set_field_widget_attributes(form_field, {
                custom_validator.name: "true"
            })
            custom_errors.append(custom_validator)
            setattr(form_field, "custom_potential_errors", custom_errors)
    def customize(self, customization):

        field_type = self.get_current_field_value("field_type")
        proxy = self.instance.proxy
        assert customization.proxy == proxy, "in QPropertyRealizationForm, customization.proxy doesn't equal instance.proxy"

        # customize form...
        self.inline_help = customization.inline_help
        self.is_nillable = customization.is_nillable
        self.is_required = customization.is_required
        self.is_hidden = customization.is_hidden
        self.is_editable = customization.is_editable
        self.is_hierarchical = customization.relationship_is_hierarchical
        self.render = not (self.is_hidden or self.is_hierarchical)  # tells the template whether or not I plan on rendering the form

        # customize fields...
        self.value_field.help_text = customization.property_description
        self.value_field.label = customization.property_title
        self.value_field.required = customization.is_required
        self.value_field.editable = customization.is_editable

        if not customization.is_editable:
            set_field_widget_attributes(self.value_field, {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            set_field_widget_attributes(self.fields["is_nil"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            set_field_widget_attributes(self.fields["nil_reason"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })

        # more in-depth customization...

        if field_type == QPropertyTypes.ATOMIC:
            atomic_value_field = self.fields["atomic_value"]
            existing_widget_attrs = atomic_value_field.widget.attrs
            custom_widget_class, custom_widget_args = ATOMIC_PROPERTY_MAP[customization.atomic_type]
            atomic_value_field.widget = custom_widget_class(custom_widget_args)
            update_field_widget_attributes(atomic_value_field, existing_widget_attrs)
            if self.instance.is_new:
                default_values = customization.default_values
                if default_values:
                    # TODO: WILL NEED TO REWRITE THIS TO COPE W/ "cardinality_max" > 1 FOR ATOMIC FIELDS
                    # TODO: (IN THAT CASE, I SHOULD PROBABLY MAKE "atomic_value" A QJSONField
                    assert len(default_values) == 1, "need to rewrite this to cope w/ 'cardinality_max' > 1 for atomic fields"
                    self.set_default_field_value("atomic_value", default_values[0])
                    self.set_default_field_value("is_complete", True)
                if customization.is_required:
                    update_field_widget_attributes(atomic_value_field, {
                        "ng-blur": "update_property_completion()",
                    })
                else:
                    self.set_default_field_value("is_complete", True)

            if customization.atomic_suggestions:
                atomic_suggestions_list = customization.atomic_suggestions.split('|')
                set_field_widget_attributes(atomic_value_field, {
                    "uib-typeahead": "option for option in [{0}] | filter:$viewValue | limitTo:{1}".format(
                        ",".join(["'{0}'".format(mark_safe(suggestion)) for suggestion in atomic_suggestions_list]),
                        TYPEAHEAD_LIMIT
                    )
                })

        elif field_type == QPropertyTypes.ENUMERATION:
            enumeration_value_field = self.fields["enumeration_value"]
            enumeration_other_value_field = self.fields["enumeration_other_value"]
            enumeration_choices = copy.copy(proxy.enumeration_choices)  # (make a copy of the value so that possibly updating it below doesn't modify the original
            if customization.enumeration_is_open:
                enumeration_choices.append({
                    "value": ENUMERATION_OTHER_CHOICE,
                    "documentation": ENUMERATION_OTHER_DOCUMENTATION,
                    "order": len(enumeration_choices) + 1,
                })
            enumeration_value_field._complete_choices = enumeration_choices

            if customization.is_required:
                update_field_widget_attributes(enumeration_value_field, {
                    "ng-blur": "update_property_completion()",
                })
                update_field_widget_attributes(enumeration_other_value_field, {
                    "ng-blur": "update_property_completion()",
                })
            else:
                self.set_default_field_value("is_complete", True)
                update_field_widget_attributes(enumeration_other_value_field, {
                    "ng-blur": "update_property_completion()",
                })

        else:  # field_type == QPropertyTypes.RELATIONSHIP
            if not customization.relationship_is_hierarchical:
                # only have to render non-hierarchical relationships in a property form...
                self.use_subforms = customization.use_subforms
                self.use_references = customization.use_references
                self.cardinality_min = customization.cardinality_min
                self.cardinality_max = customization.cardinality_max
            if not customization.is_required:
                self.set_default_field_value("is_complete", True)

        self.customization = customization
    def __init__(self, *args, **kwargs):

        super(MetadataModelForm, self).__init__(*args, **kwargs)

        set_field_widget_attributes(self.fields["title"], {"size": 64})
 def __init__(self, *args, **kwargs):
     super(QProjectForm, self).__init__(*args, **kwargs)
     for field in self.fields.itervalues():
         update_field_widget_attributes(field, {"class": "form-control form-control-md"})
     set_field_widget_attributes(self.fields["name"], {"readonly": True, "ng-disabled": "true"})
     set_field_widget_attributes(self.fields["description"], {"rows": 2})
Exemple #17
0
    def __init__(self, *args, **kwargs):
        super(QPropertyCustomizationForm, self).__init__(*args, **kwargs)

        proxy = self.get_proxy()
        field_type = self.get_field_type()

        if field_type == QPropertyTypes.ATOMIC:
            # things to do for ATOMIC fields...
            # TODO: THIS IS NO LONGER TRUE; "atomic_type" IS NOW A REQUIRED FIELD W/ A DEFAULT VALUE
            # # since atomic_fields only shows up if this is an ATOMIC field, it cannot be required
            # # but when I do display it, I can force users to make a choice
            # atomic_type_field = self.fields["atomic_type"]
            # atomic_type_field.required = True
            # atomic_type_field.empty_label = None
            # atomic_type_field.choices.remove(EMPTY_CHOICE[0])
            set_field_widget_attributes(self.fields["atomic_suggestions"], {"rows": 2})
            update_field_widget_attributes(self.fields["atomic_type"], {"class": "select single show-tick"})

        elif field_type == QPropertyTypes.ENUMERATION:
            # things to do for ENUMERATION fields...
            self.unbootstrap_fields(["enumeration_open", ])
            # choices = proxy.enumeration_choices.split('|')
            # enumeration_choices_field = self.fields["enumeration_choices"]
            # enumeration_default_field = self.fields["enumeration_default"]
            # enumeration_choices_field.set_choices(choices)
            # enumeration_default_field.set_choices(choices)
            # update_field_widget_attributes(enumeration_choices_field, {"class": "select multiple show-tick"})
            # update_field_widget_attributes(enumeration_default_field, {"class": "select multiple show-tick"})
            # if is_new_property:
            #     self.initial["enumeration_choices"] = choices

        else:  # field_type == QPropertyTypes.RELATIONSHIP
            # things to do for RELATIONSHIP fields...
            self.unbootstrap_fields(["relationship_show_subform"])
            update_field_widget_attributes(self.fields["relationship_show_subform"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            self.fields["subform_targets"].choices = [
                (relationship_subform_customization.get_key(), str(relationship_subform_customization.proxy))
                for relationship_subform_customization in self.instance.relationship_target_model_customizations(manager="allow_unsaved_relationship_target_model_customizations_manager").all()
            ]
            update_field_widget_attributes(self.fields["subform_targets"], {"class": "select single show-tick"})

        # things to do for ALL fields...

        # TODO: DOUBLE-CHECK THAT I SHOULD SET ".initial[key]" and not ".fields[key].initial"
        self.initial["key"] = self.instance.get_key()
        self.initial["category_key"] = self.instance.category.get_key()

        if proxy.is_required():
            # if a property is required by the CIM
            # (then property.reset() will have set the "required" field to True)
            # then don't allow users to change the "is_required" or "is_hidden" fields
            update_field_widget_attributes(self.fields["is_required"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            update_field_widget_attributes(self.fields["is_hidden"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })

        self.unbootstrap_fields(["is_hidden", "is_required", "is_editable", "is_nillable", "inline_help", ])
        set_field_widget_attributes(self.fields["documentation"], {"rows": 2})
    def __init__(self, *args, **kwargs):
        super(QStandardPropertyCustomizationForm, self).__init__(*args, **kwargs)

        is_new_property = not self.instance.pk
        proxy = self.get_proxy()
        field_type = self.get_field_type()

        if field_type == QPropertyTypes.ATOMIC:
            # things to do for ATOMIC fields...
            # TODO: THIS IS NO LONGER TRUE; "atomic_type" IS NOW A REQUIRED FIELD W/ A DEFAULT VALUE
            # # since atomic_fields only shows up if this is an ATOMIC field, it cannot be required
            # # but when I do display it, I can force users to make a choice
            # atomic_type_field = self.fields["atomic_type"]
            # atomic_type_field.required = True
            # atomic_type_field.empty_label = None
            # atomic_type_field.choices.remove(EMPTY_CHOICE[0])
            set_field_widget_attributes(self.fields["atomic_suggestions"], {"rows": 2})
            update_field_widget_attributes(self.fields["atomic_type"], {"class": "select single show-tick"})

        elif field_type == QPropertyTypes.ENUMERATION:
            # things to do for ENUMERATION fields...
            self.unbootstrap_fields(["enumeration_open", "enumeration_multi", "enumeration_nullable", ])
            choices = proxy.enumeration_choices.split('|')
            enumeration_choices_field = self.fields["enumeration_choices"]
            enumeration_default_field = self.fields["enumeration_default"]
            enumeration_choices_field.set_choices(choices)
            enumeration_default_field.set_choices(choices)
            update_field_widget_attributes(enumeration_choices_field, {"class": "select multiple show-tick"})
            update_field_widget_attributes(enumeration_default_field, {"class": "select multiple show-tick"})
            if is_new_property:
                self.initial["enumeration_choices"] = choices

        else:  # field_type == QPropertyTypes.RELATIONSHIP
            # things to do for RELATIONSHIP fields...
            self.unbootstrap_fields(["relationship_show_subform"])
            update_field_widget_attributes(self.fields["relationship_show_subform"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            update_field_widget_attributes(self.fields["cardinality"], {
                "class": "cardinality",
            })

        # things to do for ALL fields...

        # TODO: DOUBLE-CHECK THAT I SHOULD SET ".initial[key]" and not ".fields[key].initial"
        self.initial["key"] = self.instance.get_key()
        try:
            self.initial["category_key"] = self.instance.category.get_key()
        except AttributeError:
            # sometimes properties in subforms don't have categories
            # ...that's okay
            pass

        if proxy.is_required():
            # if a property is required by the CIM
            # (then property.reset() will have set the "required" field to True)
            # then don't allow users to change the "required" or "displayed" fields
            update_field_widget_attributes(self.fields["required"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })
            update_field_widget_attributes(self.fields["displayed"], {
                "ng-disabled": "true",
                "readonly": "readonly",
            })

        self.unbootstrap_fields(["displayed", "required", "editable", "unique", "inline_help", "inherited", ])
        set_field_widget_attributes(self.fields["documentation"], {"rows": 2})
 def add_server_errors_to_field(self, field_name):
     # adds the possibility of rendering a server error on a given field
     field = self.fields[field_name]
     set_field_widget_attributes(field, {
         "servererror": "true",
     })