def resolve_field_path_via_geographies(field_path, manager, related_models): """ Resolve the given field path in case its not absolute. For instance, if it is 'block' and one of our related models accessible via geographies__relatedmodel has that property, return 'geographies_[scope_id]__relatedmodel__block' It will also be tested against the main manager after all related models fail, e.g. manager.values(field_path) if successful would simply return field_path :param field_path: django field path. e.g. du or built_form__name :param manager: The main manager by which the related models are resolved and by which the full path is computed :param related_models: models joined to the manager. For instance. manager.model is CanvasFeature, a related_model could be CensusBlock, which might be related to the former via 'geographies_[scope_id]__censusblock9rel'. The relationship is computed by assuming that the related model is related by geographies and looking for a field matching its type :return: """ from footprint.main.models.feature.feature_class_creator import FeatureClassCreator feature_class_creator = FeatureClassCreator.from_dynamic_model_class(manager.model) for related_model in related_models: try: # See if the field_name resolves # There's probably a more efficient way to do this related_model.objects.values(field_path) resolved_field_path = field_path except: # See if the first segment matches the related_model db_entity_key first_segment = field_path.split("__")[0] if first_segment != related_model.db_entity_key: # If not, move on continue # Take all but the first segment resolved_field_path = "__".join(field_path.split("__")[1:]) # Success, find the path to this model from geographies geography_class = feature_class_creator.common_geography_class(related_model) geographies_field = feature_class_creator.geographies_field( feature_class_creator.common_geography_scope(related_model) ) geography_related_field_name = resolve_queryable_name_of_type(geography_class, related_model) return "%s__%s__%s" % (geographies_field.name, geography_related_field_name, resolved_field_path) # See if it matches the main model try: if field_path.split("__")[0] == manager.model.db_entity_key: # If the manager model db_entity_key was used in the path, just strip it out updated_field_path = "__".join(field_path.split("__")[1:]) manager.values(updated_field_path) else: # Otherwise test query with the full path updated_field_path = field_path manager.values(updated_field_path) # Success, return the field_path return updated_field_path except: logger.exception( "Cannot resolve field path %s to the main model %s or any joined models %s", field_path, manager.model, related_models, ) raise
def resolve_field_path_via_geographies(field_path, manager, related_models): """ Resolve the given field path in case its not absolute. For instance, if it is 'block' and one of our related models accessible via geographies__relatedmodel has that property, return 'geographies_[scope_id]__relatedmodel__block' It will also be tested against the main manager after all related models fail, e.g. manager.values(field_path) if successful would simply return field_path :param field_path: django field path. e.g. du or built_form__name :param manager: The main manager by which the related models are resolved and by which the full path is computed :param related_models: models joined to the manager. For instance. manager.model is CanvasFeature, a related_model could be CensusBlock, which might be related to the former via 'geographies_[scope_id]__censusblock9rel'. The relationship is computed by assuming that the related model is related by geographies and looking for a field matching its type :return: """ from footprint.main.models.feature.feature_class_creator import FeatureClassCreator feature_class_creator = FeatureClassCreator.from_dynamic_model_class( manager.model) for related_model in related_models: try: # See if the field_name resolves # There's probably a more efficient way to do this related_model.objects.values(field_path) resolved_field_path = field_path except: # See if the first segment matches the related_model db_entity_key first_segment = field_path.split('__')[0] if first_segment != related_model.db_entity_key: # If not, move on continue # Take all but the first segment resolved_field_path = '__'.join(field_path.split('__')[1:]) # Success, find the path to this model from geographies geography_class = feature_class_creator.common_geography_class( related_model) geographies_field = feature_class_creator.geographies_field( feature_class_creator.common_geography_scope(related_model)) geography_related_field_name = resolve_queryable_name_of_type( geography_class, related_model) return '%s__%s__%s' % (geographies_field.name, geography_related_field_name, resolved_field_path) # See if it matches the main model try: if field_path.split('__')[0] == manager.model.db_entity_key: # If the manager model db_entity_key was used in the path, just strip it out updated_field_path = '__'.join(field_path.split('__')[1:]) manager.values(updated_field_path) else: # Otherwise test query with the full path updated_field_path = field_path manager.values(updated_field_path) # Success, return the field_path return updated_field_path except: logger.exception( 'Cannot resolve field path %s to the main model %s or any joined models %s', field_path, manager.model, related_models) raise
def resolve_related_model_pk(db_entity_key): related_model = config_entity.db_entity_feature_class(db_entity_key) # The common Geography class geography_class = feature_class_creator.common_geography_class(related_model) geography_scope = feature_class_creator.common_geography_scope(related_model) logger.warn("Resolved geography scope %s", geography_scope) # Find the geographies ManyToMany fields that relates this model to the related_model # via a Geography class. Which geography class depends on their common geography scope geographies_field = feature_class_creator.geographies_field(geography_scope) try: # Find the queryable field name from the geography class to the related model related_model_geographies_field_name = resolve_queryable_name_of_type(geography_class, related_model) except: # Sometimes the geography class hasn't had its fields cached properly. Fix here clear_many_cache(geography_class) related_model_geographies_field_name = resolve_queryable_name_of_type(geography_class, related_model) return "%s__%s__pk" % (geographies_field.name, related_model_geographies_field_name)
def resolve_related_model_pk(db_entity_key): related_model = config_entity.db_entity_feature_class(db_entity_key) # The common Geography class geography_class = feature_class_creator.common_geography_class(related_model) geography_scope = feature_class_creator.common_geography_scope(related_model) logger.warn("Resolved geography scope %s", geography_scope) # Find the geographies ManyToMany fields that relates this model to the related_model # via a Geography class. Which geography class depends on their common geography scope geographies_field = feature_class_creator.geographies_field(geography_scope) try: # Find the queryable field name from the geography class to the related model related_model_geographies_field_name = resolve_queryable_name_of_type(geography_class, related_model) except: # Sometimes the geography class hasn't had its fields cached properly. Fix here clear_many_cache(geography_class) related_model_geographies_field_name = resolve_queryable_name_of_type(geography_class, related_model) return '%s__%s__pk' % (geographies_field.name, related_model_geographies_field_name)
def resolve_related_model_path_via_geographies(manager, related_model): """ Returns the query string path 'geographies_[scope_id]__[field name of the related model form the main model]' The scope_id is the id of the ConfigEntity that both models share in common by ascending the ConfigEntity hierarchy starting at each models' geography_scope """ from footprint.main.models.feature.feature_class_creator import FeatureClassCreator feature_class_creator = FeatureClassCreator.from_dynamic_model_class(manager.model) geography_scope = feature_class_creator.common_geography_scope(related_model) geographies_field = feature_class_creator.geographies_field(geography_scope) geography_class = feature_class_creator.common_geography_class(related_model) geography_related_field_name = resolve_queryable_name_of_type(geography_class, related_model) return '%s__%s' % (geographies_field.name, geography_related_field_name)
def resolve_related_model_path_via_geographies(manager, related_model): """ Returns the query string path 'geographies_[scope_id]__[field name of the related model form the main model]' The scope_id is the id of the ConfigEntity that both models share in common by ascending the ConfigEntity hierarchy starting at each models' geography_scope """ from footprint.main.models.feature.feature_class_creator import FeatureClassCreator feature_class_creator = FeatureClassCreator.from_dynamic_model_class(manager.model) geography_scope = feature_class_creator.common_geography_scope(related_model) geographies_field = feature_class_creator.geographies_field(geography_scope) geography_class = feature_class_creator.common_geography_class(related_model) geography_related_field_name = resolve_queryable_name_of_type(geography_class, related_model) return "%s__%s" % (geographies_field.name, geography_related_field_name)