Ejemplo n.º 1
0
    def clean_linked_reference_dataset(self):
        cleaned = self.cleaned_data
        field = self.instance
        if cleaned.get('data_type') == ReferenceDatasetField.DATA_TYPE_FOREIGN_KEY:
            # Ensure a reference dataset to link to was provided
            if cleaned.get('linked_reference_dataset') is None:
                raise ValidationError('Please select a reference data set to link to')

            # Ensure a reference dataset field cannot link to it's own parent
            if self.reference_dataset == cleaned['linked_reference_dataset']:
                raise ValidationError(
                    'A reference dataset record cannot point to itself'
                )

            # Do not allow users to change a foreign key relationship if records exist
            if (
                field.id
                and cleaned['linked_reference_dataset']
                != field.linked_reference_dataset
            ):
                matching_records = self.reference_dataset.get_records().exclude(
                    **{field.column_name: None}
                )
                if matching_records.exists():
                    raise forms.ValidationError(
                        'Unable to change linked reference dataset when '
                        'relations exist in this dataset'
                    )

            # If this reference dataset syncs with an external database we need
            # to ensure any linked fields also sync with the same database
            ext_db = self.reference_dataset.external_database
            linked_ext_db = cleaned['linked_reference_dataset'].external_database
            if ext_db is not None and ext_db != linked_ext_db:
                raise forms.ValidationError(
                    'Linked reference dataset does not exist on external database {}'.format(
                        ext_db.memorable_name
                    )
                )

            # Ensure a linked to reference dataset doesn't link back to this dataset
            if has_circular_link(
                self.reference_dataset, cleaned['linked_reference_dataset']
            ):
                raise ValidationError(
                    'Unable to link to a dataset that links to this dataset'
                )

        return cleaned['linked_reference_dataset']
Ejemplo n.º 2
0
    def save(
        self, force_insert=False, force_update=False, using=None, update_fields=None
    ):
        """
        On ReferenceDatasetField save update the associated table.
        :param force_insert:
        :param force_update:
        :param using:
        :param update_fields:
        :return:
        """
        ref_dataset = self.reference_dataset

        # Disallow circular linking of reference datasets
        if self.data_type == self.DATA_TYPE_FOREIGN_KEY and has_circular_link(
            self.reference_dataset, self.linked_reference_dataset
        ):
            raise ValidationError(
                'Unable to link reference datasets back to each other'
            )

        # If this is a newly created field add it to the db
        if self.id is None:
            self._add_column_to_db()
        else:
            # Otherwise update where necessary
            if self._original_column_name != self.column_name:
                self._update_db_column_name()
            if self._original_data_type != self.data_type:
                self._update_db_column_data_type()

        # Increment reference dataset major version if this is not the first save
        if (
            ref_dataset.major_version > 1 or ref_dataset.minor_version > 0
        ) or ref_dataset.get_records().exists():
            self.reference_dataset.increment_major_version()
        super().save()