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']
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()