def create_related_field(self, field_name, related_field_configuration): """ Creates a ForeignKey or ManyToMany field based on related_field_configuration :param field_name: :param related_field_configuration: A dict containing related_key or related_class_name related_key: the instance of the sibling key of the config_entity whose dynamic_model_class is the relation type. For DbEntity/Features this would be the db_entity_key and the dynamic_model_class would be its FeatureClass For AnalysisModule this would be the analysis module key and its dynamic class related_class_name: rather than related_key, any model class, such as BuiltForm, to relate to. single: if True this is a ForeignKey (toOne) relationship. Otherwise a ManyToMany is created :return: A two-item tuple. First item is the field name and the second is the field. """ config_entity = ConfigEntity._subclassed_by_id(self.configuration.scope) # TODO temp coverage of a key name name change related_field_configuration['related_key'] = related_field_configuration.get('related_key', related_field_configuration.get('related_db_entity_key')) if related_field_configuration.get('related_key', False): # field name matches name of peer self.db_entity_key--get it's feature class name related_db_entity = get_single_value_or_none(config_entity.computed_db_entities(key=related_field_configuration['related_key'])) # Always call with no_ensure=True since the config_entity is the same. Otherwise we'd get infinite recursion related_class_name_or_model = self.__class__(self.config_entity, related_db_entity, no_ensure=True).dynamic_model_class() elif related_field_configuration.get('related_class_name', None): # A model class such as BuiltForm related_class_name_or_model = resolve_module_attr(related_field_configuration['related_class_name']) else: raise Exception("No related_key or related_class_name found on feature_class_configuration for self.configuration.key %s" % self.configuration.key) logger.info('Creating %r related field for %s using %s', related_field_configuration.get('single', None) and 'single' or 'm2m', field_name, related_field_configuration) if related_field_configuration.get('single', None): return [field_name, models.ForeignKey(related_class_name_or_model, null=True)] else: return [field_name, models.ManyToManyField(related_class_name_or_model, # Pass a custom, readable table name for the through class for ManyToMany relations db_table='"{schema}"."{table}_{field_name}"'.format( schema=config_entity.schema(), table=self.configuration.key, field_name=field_name))]
def create_related_field(self, field_name, related_field_configuration): """ Creates a ForeignKey or ManyToMany field based on related_field_configuration :param field_name: :param related_field_configuration: A dict containing related_key or related_class_name related_key: the instance of the sibling key of the config_entity whose dynamic_model_class is the relation type. For DbEntity/Features this would be the db_entity_key and the dynamic_model_class would be its FeatureClass For AnalysisModule this would be the analysis module key and its dynamic class related_class_name: rather than related_key, any model class, such as BuiltForm, to relate to. single: if True this is a ForeignKey (toOne) relationship. Otherwise a ManyToMany is created :return: A two-item tuple. First item is the field name and the second is the field. """ config_entity = ConfigEntity._subclassed_by_id(self.configuration.scope) # TODO temp coverage of a key name name change related_field_configuration['related_key'] = related_field_configuration.get('related_key', related_field_configuration.get('related_db_entity_key')) if related_field_configuration.get('related_key', False): # field name matches name of peer self.db_entity_key--get it's feature class name related_db_entity = get_single_value_or_none(config_entity.computed_db_entities(key=related_field_configuration['related_key'])) # Always call with no_ensure=True since the config_entity is the same. Otherwise we'd get infinite recursion related_class_name_or_model = self.__class__(self.config_entity, related_db_entity, no_ensure=True).dynamic_model_class() elif related_field_configuration.get('related_class_name', None): # A model class such as BuiltForm related_class_name_or_model = resolve_module_attr(related_field_configuration['related_class_name']) else: raise Exception("No related_key or related_class_name found on feature_class_configuration for self.configuration.key %s" % self.configuration.key) logger.info('Creating %r related field for %s using %s', related_field_configuration.get('single', None) and 'single' or 'm2m', field_name, related_field_configuration) if related_field_configuration.get('single', None): return [field_name, models.ForeignKey(related_class_name_or_model, null=True)] else: return [field_name, models.ManyToManyField(related_class_name_or_model, # Pass a custom, readable table name for the through class for ManyToMany relations db_table='"{schema}"."{table}_{field_name}"'.format( schema=config_entity.schema(), table=self.configuration.key, field_name=field_name))]
def geography_scope(self): return ConfigEntity._subclassed_by_id(self.configuration.geography_scope \ if self.configuration and self.configuration.key else \ self.config_entity.id)