def default_db_entities(self, **kwargs):
        """
        Project specific SACOG additional db_entities
        :param default_dict:
        :return:
        """

        project = self.config_entity
        # The DbEntity keyspace. These keys have no prefix
        Key = ScagDmDbEntityKey
        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate

        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        return super(ScagDmProjectFixture, self).default_db_entities() + [
            update_or_create_db_entity(
                project,
                DbEntity(
                    name='SCAG Existing Land Use Parcels 2012',
                    key=Key.EXISTING_LAND_USE_PARCELS_2012,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=ExistingLandUseParcel,
                        import_from_db_entity_key=Key.
                        REGION_EXISTING_LAND_USE_PARCELS,
                        filter_query=dict(city=project.name),
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='scag_lu'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                project,
                DbEntity(
                    key=Key.CITY_BOUNDARY,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=CityBoundary,
                        import_from_db_entity_key=Key.REGION_CITY_BOUNDARY,
                        filter_query=dict(city=project.name),
                        use_for_bounds=True),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=GeographicIntersection.polygon_to_centroid
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ]))
        ]
    def complete_or_create_feature_class_configuration(
            self, feature_class_configuration, **overrides):
        """
            Clones the given feature_class_configuration to make it specific to the ConfigEntity
            If the feature_class_configuration is null a simple one is created
            :param feature_class_configuration: Used for the basis of cloning from another DbEntity, or
            as the preconfigured instance that was defined in an initializer, such as default_project.py
            :param overrides: Override anything in the feature_class_configuration. This is used for cloning
            when we need to specify generated=YES, source_from_origin_layer_selection=True, etc
        """
        if self.db_entity and self.db_entity.no_feature_class_configuration:
            # If nothing is passed it means that the DbEntity doesn't represent a feature table, e.g. background imagery
            return None

        key = self.db_entity.key if self.db_entity else self.DETACHED_FROM_DB_ENTITY

        return FeatureClassConfiguration(**merge(
            dict(
                # Indicates that the configuration was generated by introspecting a table, rather than by deliberate configuration
                generated=False,
                # Indicates that the features should be created from an origin LayerSelection features.
                source_from_origin_layer_selection=False,
                # The origin Layer id
                origin_layer_id=None,
                # The user of the origin layer
                origin_user=None,
                # The default data_importer for features
                # The default imports based on the url of the db_entity--usually a special database url
                data_importer=None,
            ),
            # Override the above with any configured attributes
            merge(feature_class_configuration.
                  __dict__, overrides) if feature_class_configuration else {},
            # Override or define ConfigEntity specific attributes
            dict(
                key=key,
                # The scope is the id of the config_entity
                scope=self.config_entity and self.config_entity.id,
                # The config_entity id scopes the geography table, except for scenarios which
                # always use their Project config_entity id as the scope
                geography_scope=self.config_entity.id,
                schema=self.config_entity.schema(),
                class_attrs=merge(
                    feature_class_configuration.
                    class_attrs if feature_class_configuration else {}, {
                        'config_entity__id': self.config_entity.id,
                        'override_db': self.config_entity.db,
                        'db_entity_key': key
                    }),
            ) if self.config_entity else dict(
                # Abstract case
                key=key,
                class_attrs=merge(
                    feature_class_configuration.
                    class_attrs if feature_class_configuration else {},
                    {'db_entity_key': key}))))
    def generate_configuration(self, fields=[]):
        """
            Creates a feature_class_configuration for db_entities not pre-configured, in other words, those that
            were uploaded.
        """

        # Use the pk for the source_id_column
        primary_key_fields = filter(lambda field: field.primary_key, fields)
        # Use the existing primary key or default to the default Django one
        # The former case applies to imported tables that have primary keys, the latter to tables that are
        # created by Django
        source_id_column = primary_key_fields[
            0].name if primary_key_fields else 'id'

        return self.complete_or_create_feature_class_configuration(
            FeatureClassConfiguration(
                fields=fields,
                source_id_column=source_id_column,
                # Generated tells us that the feature_class_configuration wasn't pre-configured in code
                generated=True))
    def clone_db_entity_and_interest_for_result(self, config_entity,
                                                existing_db_entity_interest,
                                                reference_db_entity_key,
                                                **kwargs):
        """
            Clone the selected db_entity of key reference_db_entity and replace any of its attributes with those
            specified in **kwargs. **kwargs should contain a unique key property
        :param config_entity
        :param existing_db_entity_interest: The existing DbEntityInterest if one exists
        :param reference_db_entity_key: key of the DbEntity to clone
        :param kwargs: replacement values containing at the very least 'key'
        :return: The DbEntityInterest which references the cloned db_entity
        """
        source_db_entity = config_entity.computed_db_entities().get(
            key=reference_db_entity_key)
        # Avoid circular reference
        from footprint.main.publishing.db_entity_publishing import clone_or_update_db_entity_and_interest

        db_entity_interest = clone_or_update_db_entity_and_interest(
            config_entity,
            source_db_entity,
            DbEntity(**merge(
                kwargs,
                dict(feature_class_configuration=FeatureClassConfiguration(
                    **merge(
                        source_db_entity.feature_class_configuration.__dict__,
                        dict(feature_class_owner=reference_db_entity_key))),
                     ))),
            existing_db_entity_interest=existing_db_entity_interest,
            override_on_update=True)
        # Run this manually here. It should be triggered by saving the DbEntity, but something
        # is disabling the publisher
        # TODO the DbEntity publihser should be turned on here so this should be neeed
        from footprint.main.publishing.user_publishing import on_db_entity_post_save_user
        on_db_entity_post_save_user(None, instance=db_entity_interest)
        return db_entity_interest
Beispiel #5
0
    def default_db_entities(self):
        """
            Region specific db_entity_setups
        :param default_dict:
        :return:
        """

        config_entity = self.config_entity
        parent_region_fixture = self.parent_fixture
        default_db_entities = parent_region_fixture.default_db_entities()
        # The DbEntity keyspace. These keys have no prefix
        Key = ScagDmDbEntityKey
        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate
        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        if isinstance(self.config_entity.parent_config_entity_subclassed,
                      GlobalConfig):
            # Block the client-level region. We just want real regions
            return []

        return default_db_entities + FixtureList([
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    name='2016 SCAG Existing Land Use Parcels',
                    key=Key.REGION_EXISTING_LAND_USE_PARCELS,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=ExistingLandUseParcel,
                        primary_geography=True,
                        primary_key='source_id',
                        primary_key_type='int',
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='scag_lu16'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.FLOOD_ZONES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=FloodZones),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.ENDANGERED_SPECIES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=EndangeredSpecies),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.CPAD_HOLDINGS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CpadHoldings),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.HABITAT_CONSERVATION_AREA,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=HabitatConservationAreas),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.COUNTY_BOUNDARY,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CountyBoundary),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(name='2040 High Quality Transit Areas',
                         key=Key.HIGH_QUALITY_TRANSIT_AREAS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=HighQualityTransitAreas),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(name='2040 High Quality Transit Corridors',
                         key=Key.HIGH_QUALITY_TRANSIT_CORRIDORS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=HighQualityTransitCorridors),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(name='2040 Major Transit Stops',
                         key=Key.MAJOR_TRANSIT_STOPS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=MajorTransitStops),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(name='2040 Transit Priority Areas',
                         key=Key.TRANSIT_PRIORITY_AREAS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=TransitPriorityAreas),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.FARMLAND,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=Farmland,
                        related_fields=dict(farmland_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_farmland_definition.ScagDmFarmlandDefinition',
                            related_class_join_field_name='farmland_code',
                            source_class_join_field_name='scag_type'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior(
                            'reference_layers_editable_attribute'),
                        intersection=GeographicIntersection.polygon_to_centroid
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.REGION_GENERAL_PLAN_PARCELS,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=GeneralPlanParcels,
                        primary_key='source_id',
                        primary_key_type='int',
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                            # Use this for the resource type, since we don't want a client-specific resource URL
                            # TODO not wired up yet
                            resource_model_class_name=
                            'footprint.main.models.built_form.ClientLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='scag_gp_code16'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=AttributeIntersection()),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.REGION_SPECIFIC_PLAN_PARCELS,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SpecificPlanParcels,
                        primary_key='source_id',
                        primary_key_type='int',
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                            resource_model_class_name=
                            'footprint.main.models.built_form.ClientLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='scag_sp_code16'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=AttributeIntersection()),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.REGION_ZONING_PARCELS,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=ZoningParcels,
                        primary_key='source_id',
                        primary_key_type='int',
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                            resource_model_class_name=
                            'footprint.main.models.built_form.ClientLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='scag_zn_code16'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=AttributeIntersection()),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.REGION_ENTITLEMENT_PARCELS_2016,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=EntitlementParcels,
                             primary_key='source_id',
                             primary_key_type='int',
                             fields=dict()),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=AttributeIntersection()),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.REGION_SCENARIO_PLANNING_ZONES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=ScenarioPlanningZones, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(name='Sphere of Influence',
                         key=Key.REGION_SPHERE_OF_INFLUENCE,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=SphereOfInfluence, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.REGION_TIER2_TAZ,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=Tier2Taz, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.CENSUS_TRACTS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CensusTracts, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.SUB_REGION,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=SubRegion, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.REGION_CITY_BOUNDARY,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CityBoundary, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('editable_feature'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            # update_or_create_db_entity(config_entity, DbEntity(
            #     key=Key.BIKE_LANE,
            #     feature_class_configuration=FeatureClassConfiguration(
            #         abstract_class=BikeLane,
            #     ),
            #     feature_behavior=FeatureBehavior(
            #         behavior=get_behavior('reference_layers_editable_attribute'),
            #         intersection=GeographicIntersection.polygon_to_centroid
            #     ),
            #     _categories=[Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION, value=DbEntityCategoryKey.REFERENCE)]
            # )),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.SEA_LEVEL_RISE,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=SeaLevelRise, ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior(
                                 'reference_layers_editable_attribute'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ]))
        ])
Beispiel #6
0
    def default_db_entities(self):
        """
            Scenarios define DbEntities specific to the Scenario. Creates a list a dictionary of configuration functionality.
            These are filtered based on whether the given scenario matches the scope in the configuration
        :return:
        """
        project = self.config_entity.parent_config_entity_subclassed

        scenario = self.config_entity
        # The DbEntity keyspace. These keys have no prefix
        Key = ScagDmDbEntityKey
        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate
        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        return super(ScagDmScenarioFixture, self).default_db_entities() + map(
            lambda db_entity_dict: update_or_create_db_entity(
                scenario, db_entity_dict['value']),
            FixtureList([
                dict(
                    class_scope=BaseScenario,
                    value=DbEntity(
                        name='2016 SCAG Existing Land Use Parcels',
                        key=Key.EXISTING_LAND_USE_PARCELS_2016,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=ExistingLandUseParcel,
                            import_from_db_entity_key=Key.
                            REGION_EXISTING_LAND_USE_PARCELS,
                            filter_query=dict(city=project.name),
                            # primary_geography=True,
                            # primary_key='source_id',
                            # primary_key_type='int',
                            fields=dict(),
                            related_fields=dict(land_use_definition=dict(
                                single=True,
                                related_class_name=
                                'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                                related_class_join_field_name='land_use',
                                source_class_join_field_name='scag_lu16'))),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('editable_feature')),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.EDITABLE_LAYER)
                        ])),
                dict(
                    class_scope=BaseScenario,
                    value=DbEntity(
                        name='2016 SCAG General Plan Parcels',
                        key=Key.GENERAL_PLAN_PARCELS,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=GeneralPlanParcels,
                            primary_key='source_id',
                            primary_key_type='int',
                            import_from_db_entity_key=Key.
                            REGION_GENERAL_PLAN_PARCELS,
                            filter_query=dict(city=project.name),
                            fields=dict(),
                            related_fields=dict(land_use_definition=dict(
                                single=True,
                                related_class_name=
                                'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                                # Use this for the resource type, since we don't want a client-specific resource URL
                                # TODO not wired up yet
                                resource_model_class_name=
                                'footprint.main.models.built_form.ClientLandUseDefinition',
                                related_class_join_field_name='land_use',
                                source_class_join_field_name='scag_gp_code16')
                                                )),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('editable_feature'),
                            intersection=AttributeIntersection()),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.EDITABLE_LAYER)
                        ])),
                dict(
                    class_scope=BaseScenario,
                    value=DbEntity(
                        name='2016 SCAG Specific Plan Parcels',
                        key=Key.SPECIFIC_PLAN_PARCELS,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=SpecificPlanParcels,
                            primary_key='source_id',
                            primary_key_type='int',
                            import_from_db_entity_key=Key.
                            REGION_SPECIFIC_PLAN_PARCELS,
                            filter_query=dict(city=project.name),
                            fields=dict(),
                            related_fields=dict(land_use_definition=dict(
                                single=True,
                                related_class_name=
                                'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                                resource_model_class_name=
                                'footprint.main.models.built_form.ClientLandUseDefinition',
                                related_class_join_field_name='land_use',
                                source_class_join_field_name='scag_sp_code16')
                                                )),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('editable_feature'),
                            intersection=AttributeIntersection()),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.EDITABLE_LAYER)
                        ])),
                dict(class_scope=BaseScenario,
                     value=DbEntity(
                         name='2016 SCAG Infill Parcels',
                         key=Key.INFILL_PARCELS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=InfillParcels,
                             import_from_db_entity_key=Key.
                             REGION_INFILL_PARCELS,
                             filter_query=dict(city=project.name),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('editable_feature'),
                             intersection=AttributeIntersection()),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.EDITABLE_LAYER)
                         ])),
                dict(
                    class_scope=BaseScenario,
                    value=DbEntity(
                        name='2016 SCAG Zoning Parcels',
                        key=Key.ZONING_PARCELS,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=ZoningParcels,
                            primary_key='source_id',
                            primary_key_type='int',
                            import_from_db_entity_key=Key.
                            REGION_ZONING_PARCELS,
                            filter_query=dict(city=project.name),
                            fields=dict(),
                            related_fields=dict(land_use_definition=dict(
                                single=True,
                                related_class_name=
                                'footprint.client.configuration.scag_dm.built_form.scag_dm_land_use_definition.ScagDmLandUseDefinition',
                                resource_model_class_name=
                                'footprint.main.models.built_form.ClientLandUseDefinition',
                                related_class_join_field_name='land_use',
                                source_class_join_field_name='scag_zn_code16')
                                                )),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('editable_feature'),
                            intersection=AttributeIntersection()),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.EDITABLE_LAYER)
                        ])),
                dict(class_scope=BaseScenario,
                     value=DbEntity(
                         name='2016 SCAG Entitlement Parcels',
                         key=Key.ENTITLEMENT_PARCELS_2016,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=EntitlementParcels,
                             primary_key='source_id',
                             primary_key_type='int',
                             import_from_db_entity_key=Key.
                             REGION_ENTITLEMENT_PARCELS_2016,
                             filter_query=dict(city=project.name),
                             fields=dict()),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('editable_feature'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.EDITABLE_LAYER)
                         ])),
                dict(class_scope=BaseScenario,
                     value=DbEntity(
                         key=Key.SCENARIO_PLANNING_ZONES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=ScenarioPlanningZones,
                             import_from_db_entity_key=Key.
                             REGION_SCENARIO_PLANNING_ZONES,
                             filter_query=dict(city=project.name),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('editable_feature'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
                dict(class_scope=BaseScenario,
                     value=DbEntity(
                         name='City/Tier2 TAZ',
                         key=Key.TIER2_TAZ,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=Tier2Taz,
                             import_from_db_entity_key=Key.REGION_TIER2_TAZ,
                             filter_query=dict(city=project.name),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('sed_editor_tool'),
                             intersection=AttributeIntersection()),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.EDITABLE_LAYER)
                         ]))
            ]).matching_scope(class_scope=self.config_entity
                              and self.config_entity.__class__))
    def default_db_entities(self, **kwargs):
        """
        Region specific SACOG db_entity_setups
        :param default_dict:
        :return:
        """

        config_entity = self.config_entity
        parent_region_fixture = self.parent_fixture
        default_db_entities = parent_region_fixture.default_db_entities()
        Key = SacogDbEntityKey

        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate
        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        if self.config_entity.key == 'sacog':
            # Block the client-level region. We just want real regions
            return []

        remote_db_entity_setups = FixtureList(
            map(
                lambda db_entity: update_or_create_db_entity(
                    config_entity, db_entity),
                self.default_remote_db_entities()))

        # TODO: Disabled the 'sacog_background' 'remote db entity' b/c it is throwing errors (2016-07-06)
        # return default_db_entities + remote_db_entity_setups + FixtureList([
        return default_db_entities + FixtureList([
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=DbEntityKey.REGION_PRIMARY_GEOGRAPHY,
                    # Override. If a name override is supplied, put it in. Otherwise leave null to derive it from the key
                    name='Urban Base Canvas (UF)',
                    # name=get_property_path(kwargs, 'overrides.%s.name' % Key.BASE),
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=CanvasFeature,
                        # The Base Feature is normally considered a primary_geography unless overridden
                        primary_geography=True,
                        primary_key='geography_id',
                        primary_key_type='int',
                        # The Base Feature is normally associated to a subclass of Geography unless overridden
                        geography_class_name=get_property_path(
                            kwargs, 'overrides.%s.geography_class_name' %
                            Key.BASE_CANVAS)
                        or 'footprint.main.models.geographies.parcel.Parcel',
                        # Create a built_form ForeignKey to a single BuiltForm,
                        # by initially joining our 'built_form_key' attribute to its 'key' attribute
                        related_fields=dict(built_form=dict(
                            single=True,
                            related_class_name=uf_model(
                                'built_form.built_form.BuiltForm'),
                            source_class_join_field_name='built_form_key',
                            related_class_join_field_name='key',
                        ))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('base_feature'), ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.CENSUS_TRACTS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CensusTract),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.CENSUS_BLOCKGROUPS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CensusBlockgroup),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.CENSUS_BLOCK,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CensusBlock),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.LIGHT_RAIL,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=SacogLightRailFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(key=Key.LIGHT_RAIL_STOPS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=SacogLightRailStopsFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.LIGHT_RAIL_STOPS_ONE_MILE,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogLightRailStopsOneMileFeature, ),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=GeographicIntersection.polygon_to_polygon
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.LIGHT_RAIL_STOPS_HALF_MILE,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogLightRailStopsHalfMileFeature),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=GeographicIntersection.polygon_to_polygon
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.LIGHT_RAIL_STOPS_QUARTER_MILE,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogLightRailStopsQuarterMileFeature),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=GeographicIntersection.polygon_to_polygon
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.VERNAL_POOL,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogVernalPoolFeature),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('environmental_constraint')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.WETLAND,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogWetlandFeature),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('environmental_constraint')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                config_entity,
                DbEntity(
                    key=Key.STREAM,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogStreamFeature),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('environmental_constraint')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
        ])
    def default_db_entities(self):
        """
            Scenarios define DbEntities specific to the Scenario. Creates a list a dictionary of configuration
            functionality. These are filtered based on whether the given scenario matches the scope in the
            configuration
        :return:
        """
        scenario = self.config_entity
        project = self.config_entity.parent_config_entity
        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate
        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        return super(SacogScenarioFixture, self).default_db_entities() + map(
            lambda db_entity_dict: update_or_create_db_entity(
                scenario, db_entity_dict['value']),
            FixtureList([
                dict(
                    class_scope=FutureScenario,
                    value=DbEntity(
                        key=DbEntityKey.INCREMENT,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=CoreIncrementFeature,
                            import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                            import_ids_only=True,
                            related_fields=dict(built_form=dict(
                                single=True,
                                related_class_name=uf_model(
                                    'built_form.built_form.BuiltForm')))),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('scenario_increment'),
                            intersection=AttributeIntersection(
                                from_attribute='id', to_attribute='id')),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.FUTURE_SCENARIO)
                        ]),
                ),
                dict(
                    class_scope=FutureScenario,
                    value=DbEntity(
                        key=DbEntityKey.END_STATE,
                        feature_class_configuration=FeatureClassConfiguration(
                            abstract_class=CanvasFeature,
                            import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                            related_fields=dict(built_form=dict(
                                single=True,
                                related_class_name=uf_model(
                                    'built_form.built_form.BuiltForm')))),
                        feature_behavior=FeatureBehavior(
                            behavior=get_behavior('scenario_end_state'),
                            intersection=AttributeIntersection(
                                from_attribute='id', to_attribute='id')),
                        _categories=[
                            Category(
                                key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                value=DbEntityCategoryKey.FUTURE_SCENARIO)
                        ]),
                ),
                dict(class_scope=FutureScenario,
                     value=DbEntity(
                         key=DbEntityKey.FUTURE_AGRICULTURE_CANVAS,
                         name='Scenario Agriculture End State',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=AgricultureFeature,
                             import_from_db_entity_key=DbEntityKey.
                             BASE_AGRICULTURE_CANVAS,
                             import_ids_only=False,
                             related_fields=dict(built_form=dict(
                                 single=True,
                                 related_class_name=uf_model(
                                     'built_form.built_form.BuiltForm'),
                                 related_class_join_field_name='key',
                                 source_class_join_field_name='built_form_key')
                                                 )),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('agriculture_scenario'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.FUTURE_SCENARIO)
                         ])),
                dict(class_scope=FutureScenario,
                     value=DbEntity(
                         key=DbEntityKey.FISCAL,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=FiscalFeature,
                             import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                             empty_table=True),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.VMT_VARIABLES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=VmtVariablesFeature,
                             import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                             import_ids_only=True,
                             filter_query=dict(),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.VMT,
                         name='Vehicle Miles Traveled Output',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=VmtFeature,
                             import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                             empty_table=True),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.ENERGY,
                         name='Energy Demand Output',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=EnergyFeature,
                             import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                             empty_table=True),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.WATER,
                         name='Water Demand Output',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=WaterFeature,
                             import_from_db_entity_key=DbEntityKey.BASE_CANVAS,
                             empty_table=True),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=AttributeIntersection(
                                 from_attribute='id', to_attribute='id')),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.PH_VARIABLES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=PhVariablesFeature,
                             import_from_db_entity_key=DbEntityKey.GRID_150M,
                             import_ids_only=True,
                             filter_query=dict(),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.PH_GRID_OUTCOMES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=PhGridOutcomesFeature,
                             import_from_db_entity_key=DbEntityKey.GRID_150M,
                             import_ids_only=True,
                             filter_query=dict(),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.PH_BLOCK_GROUP_OUTCOMES,
                         name='Public Health Output',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=PhBlockGroupOutcomesFeature,
                             import_from_db_entity_key=DbEntityKey.GRID_150M,
                             import_ids_only=True,
                             filter_query=dict(),
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ])),
                dict(class_scope=Scenario,
                     value=DbEntity(
                         key=DbEntityKey.PH_OUTCOMES_SUMMARY,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=PhOutcomesSummary,
                             no_table_associations=True,
                             empty_table=True,
                         ),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.ANALYSIS_RESULTS)
                         ]))
            ]).matching_scope(class_scope=self.config_entity
                              and self.config_entity.__class__))
Beispiel #9
0
 def feature_class_configuration_as_dict(self, value):
     self.feature_class_configuration = FeatureClassConfiguration(
         **value) if isinstance(value, dict) else value
    def default_db_entities(self, **kwargs):
        """
        Project specific SACOG additional db_entities
        :param default_dict:
        :return:
        """
        project = self.config_entity
        # The DbEntity keyspace. These keys have no prefix
        Key = SacogDbEntityKey

        # The Behavior keyspace
        behavior_key = BehaviorKey.Fab.ricate
        # Used to load Behaviors defined elsewhere
        get_behavior = lambda key: Behavior.objects.get(key=behavior_key(key))

        return super(SacogProjectFixture, self).default_db_entities() + [
            update_or_create_db_entity(
                project,
                DbEntity(
                    key=DbEntityKey.BASE_CANVAS,
                    # Override. If a name override is supplied, put it in. Otherwise leave null to derive it from the key
                    name='UF Urban Base Canvas',
                    # name=get_property_path(kwargs, 'overrides.%s.name' % Key.BASE),
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=CanvasFeature,
                        # The Base Feature is normally considered a primary_geography unless overridden
                        primary_geography=get_property_path(
                            kwargs, 'overrides.%s.primary_geography' %
                            Key.BASE_CANVAS) or True,
                        primary_key='geography_id',
                        primary_key_type='int',
                        # The Base Feature is normally associated to a subclass of Geography unless overridden
                        geography_class_name=get_property_path(
                            kwargs, 'overrides.%s.geography_class_name' %
                            Key.BASE_CANVAS)
                        or 'footprint.main.models.geographies.parcel.Parcel',
                        # Create a built_form ForeignKey to a single BuiltForm,
                        # by initially joining our 'built_form_key' attribute to its 'key' attribute
                        related_fields=dict(built_form=dict(
                            single=True,
                            related_class_name=uf_model(
                                'built_form.built_form.BuiltForm'),
                            source_class_join_field_name='built_form_key',
                            related_class_join_field_name='key',
                        ))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('base_feature'), ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                project,
                DbEntity(
                    key=Key.EXISTING_LAND_USE_PARCELS,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=SacogExistingLandUseParcelFeature,
                        primary_key='geography_id',
                        primary_key_type='int',
                        fields=dict(),
                        related_fields=dict(land_use_definition=dict(
                            single=True,
                            related_class_name=
                            'footprint.client.configuration.sacog.built_form.sacog_land_use_definition.SacogLandUseDefinition',
                            resource_model_class_name=
                            'footprint.main.models.built_form.ClientLandUseDefinition',
                            related_class_join_field_name='land_use',
                            source_class_join_field_name='land_use'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('reference'),
                        intersection=AttributeIntersection(from_attribute='id',
                                                           to_attribute='id')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                project,
                DbEntity(
                    key=DbEntityKey.BASE_AGRICULTURE_CANVAS,
                    name='UF Agriculture Base Canvas (RUCS)',
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=AgricultureFeature,
                        primary_key='geography_id',
                        primary_key_type='varchar',
                        # Create a built_form ForeignKey to a single BuiltForm,
                        # by initially joining our 'built_form_key' attribute to its 'key' attribute
                        related_fields=dict(built_form=dict(
                            single=True,
                            related_class_name=
                            'footprint.main.models.built_form.built_form.BuiltForm',
                            related_class_join_field_name='key',
                            source_class_join_field_name='built_form_key'))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('base_agriculture'),
                        intersection=AttributeIntersection(
                            join_type='attribute')),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=Key.ELK_GROVE_LAND_USE_PARCELS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=ElkGroveLandUseParcel),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             centroid_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=Key.CENSUS_RATES,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=CensusRatesFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('reference'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=Key.GRID_150M,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=PhGridFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(
                    key=DbEntityKey.CLIMATE_ZONES,
                    feature_class_configuration=FeatureClassConfiguration(
                        abstract_class=ClimateZoneFeature,
                        related_fields=dict(
                            evapotranspiration_zone=dict(
                                single=True,
                                related_class_name=uf_model(
                                    'policy.water.evapotranspiration_baseline.EvapotranspirationBaseline'
                                ),
                                related_class_join_field_name='zone',
                                source_class_join_field_name=
                                'evapotranspiration_zone_id'),
                            forecasting_climate_zone=dict(
                                single=True,
                                related_class_name=uf_model(
                                    'policy.energy.commercial_energy_baseline.CommercialEnergyBaseline'
                                ),
                                related_class_join_field_name='zone',
                                source_class_join_field_name=
                                'forecasting_climate_zone_id'),
                            title_24_zone=dict(
                                single=True,
                                related_class_name=uf_model(
                                    'policy.energy.residential_energy_baseline.ResidentialEnergyBaseline'
                                ),
                                related_class_join_field_name='zone',
                                source_class_join_field_name='title_24_zone_id'
                            ))),
                    feature_behavior=FeatureBehavior(
                        behavior=get_behavior('internal_analysis'),
                        intersection=GeographicIntersection.polygon_to_centroid
                    ),
                    _categories=[
                        Category(key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                    ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=DbEntityKey.VMT_FUTURE_TRIP_LENGTHS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=VmtTripLengthsFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=DbEntityKey.VMT_BASE_TRIP_LENGTHS,
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=VmtTripLengthsFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_centroid),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=Key.BASE_TRANSIT_STOPS,
                         name='GTFS Transit Stops: 2014',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=TransitStopFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
            update_or_create_db_entity(
                project,
                DbEntity(key=Key.FUTURE_TRANSIT_STOPS,
                         name='GTFS and Future Transit Stops: 2040',
                         feature_class_configuration=FeatureClassConfiguration(
                             abstract_class=TransitStopFeature),
                         feature_behavior=FeatureBehavior(
                             behavior=get_behavior('internal_analysis'),
                             intersection=GeographicIntersection.
                             polygon_to_polygon),
                         _categories=[
                             Category(
                                 key=DbEntityCategoryKey.KEY_CLASSIFICATION,
                                 value=DbEntityCategoryKey.REFERENCE)
                         ])),
        ]
Beispiel #11
0
def clone_or_update_db_entity_and_interest(config_entity,
                                           source_db_entity,
                                           db_entity,
                                           existing_db_entity_interest=None,
                                           override_on_update=False):
    """
        Clones or updates the source_db_entity modified with the given kwargs (including possibly the key) into this ConfigEntity.
        This is used for a duplicate clone from one ConfigEntity (same DbEntity key) to another and also for
        creating a modified DbEntity for a Result from a non-Result DbEntity (different DbEntity key). A third case for this
        method is cloning a DbEntity within a ConfigEntity, which is not yet implemented.

        If the kwargs['override_on_update'] is True, the kwargs should override the target DbEntity attribute values on update.
        This is useful for the Result clone case where we want to pick up updates to the source DbEntity. But in the straight
        clone case we want to make the target DbEntity independent of the source once it is created.
        Returns the DbEntityInterest

        :param: config_entity. The config_entity of the DbEntities
        :param: Optional source_db_entity. The source of the clone
        :param: db_entity. DbEntity of attributes matching the DbEntity that need to override those of the source_db_entity. This might be the
        key, schema, etc.
        Also for db_entity.feature_class_owner, default None, is passed in for Results that are copying
        a reference DbEntity's feature_class_configuration with the db_entity key of the onwer. We don't want the result version of the feature_class_configuration
        to be used to create the feature_class tables, because that would make foreign key references point to the
        wrong feature class parents (which are named by the DbEntity id). phwewww!
        :param: existing_db_entity_interest: Optional DbEntityInterest if it already exists for the clone
        :param: override_on_update: Default False, optional and is described above.
    """

    # Do a forced adoption of DbEntityInterests from the parent ConfigEntity. This makes sure that ConfigEntity has
    # the parent's DbEntityInterests before adding any of its own. Otherwise the parent's are never adopted and
    # are created from the db_entity_configurations instead, which is minimally less efficient
    # See _adopt_from_donor docs for an explanation.
    config_entity._adopt_from_donor('db_entities', True)

    # TODO Update to newer cleaner configuration style
    # key is always resolved by the db_entity or else the source DbEntity key
    key = db_entity.key or source_db_entity.key

    feature_behavior = db_entity._feature_behavior
    if existing_db_entity_interest:
        # Merge existing DbEntity data, including the id. Manually merge feature_behavior since it's not a real
        # property
        db_entity.__dict__.update(
            merge(
                model_dict(existing_db_entity_interest.db_entity,
                           include_primary_key=True),
                dict(_feature_behavior=existing_db_entity_interest.db_entity.
                     feature_behavior)))
    if not db_entity._feature_behavior:
        from footprint.main.publishing.config_entity_initialization import get_behavior
        # If we don't already have a feature_behavior get it from the source DbEntity but 0 the id to make a copy
        # We'll also 0 out the Intersection of the FeatureBehavior and pass it to the FeatureBehavior creator
        # If we don't have a source_db_entity then create a default FeatureBehavior
        feature_behavior = source_db_entity.feature_behavior if \
            source_db_entity else  \
            FeatureBehavior(
                behavior=get_behavior('reference')
            )
        feature_behavior.id = None

    # Prefer the db_entity values over those of the source_db_entity
    db_entity.__dict__.update(merge(
        # Start with the source attributes
        model_dict(source_db_entity) if source_db_entity else {},
        # Copy the feature_behavior by assigning it to the temp property _feature_behavior
        # Prefer the FeatureBehavior of the new DbEntity (for the Result case)
        dict(_feature_behavior=feature_behavior),
        # Override with the initial clone overrides or existing clone values.
        model_dict(db_entity),
        # If update_on_override then overwrite the clone with the source values
        # This is for the case of updating the source configuration and wanting to mirror changes to the Result DbEntities
        remove_keys(model_dict(source_db_entity), ['key', 'schema', 'name']) if source_db_entity and override_on_update else {},
        # Set the clone source key if different than the target key
        dict(source_db_entity_key=source_db_entity.key) if source_db_entity and source_db_entity.key != key else {},
        dict(
             # Override feature_class_configuration keys if specified in the kwargs and create_or_update_on_override is True
             feature_class_configuration=FeatureClassConfiguration(**merge(
                # start with the source's attributes
                source_db_entity.feature_class_configuration.__dict__ if source_db_entity else {},
                # override with all those present on the clone if create_or_update_on_override is false, if true add only those unspecified on the source
                # The only exception is abstract_class_name, which must always come from the source
                remove_keys(db_entity.feature_class_configuration.__dict__,
                            source_db_entity.feature_class_configuration.__dict__.keys() if \
                                source_db_entity and override_on_update else \
                                ['abstract_class_name']
                            ),
                # feature_class_owner is set to the owning db_entity key for a Result DbEntity creation so that
                # the result feature_class_configuration doesn't create feature classes/tables
                # We either copy this value from the source feature_class_configuration (clone case) or get it from the kwargs (create Result DbEntity case)
                dict(
                    feature_class_owner=source_db_entity.feature_class_configuration.feature_class_owner if \
                        source_db_entity else \
                        db_entity.feature_class_configuration.feature_class_owner,
                )
             ))
        )
    ))
    # There must be a creator of a new DbEntity. The updater is that of the source DbEntity or simply the creator
    try:
        db_entity.creator = db_entity.creator
    except:
        db_entity.creator = source_db_entity.creator
    logger.debug(db_entity.creator.__class__)
    try:
        db_entity.updater = db_entity.updater
    except:
        db_entity.updater = db_entity.creator
    # Persist the feature_behavior
    FeatureBehavior._no_post_save_publishing = True
    db_entity.update_or_create_feature_behavior(db_entity._feature_behavior)
    # # save to persist the db_entity's knowledge of its behavior
    # db_entity.save()
    FeatureBehavior._no_post_save_publishing = False

    # This will trigger DbEntity post-save publishing, but the only thing that actually
    # runs is UserPublishing in order to give users permission to the DbEntity
    # The other publishers detect that the DbEntity has a source_db_entity_key and quit
    db_entity_interest = update_or_create_db_entity_and_interest(
        config_entity, db_entity)[0]

    # Copy the categories from the source if it exists
    if source_db_entity:
        db_entity_interest.db_entity.categories.add(
            *source_db_entity.categories.all())

    return db_entity_interest
Beispiel #12
0
def crud_db_entities(config_entity, crud, db_entity_keys=None):
    """
        Creates or updates the db_entities of the ConfigEntity
    :param config_entity
    :param crud CrudKey.CREATE, CrudType.CLONE, CrudType.UPDATE, CrudType.SYNC, CrudType.DELETE (unimplemented)
    :return:
    """
    from footprint.client.configuration.fixture import ConfigEntityFixture
    # If not present, create the database schema for this ConfigEntity's feature table data
    PGNamespace.objects.create_schema(config_entity.schema())
    client_fixture = ConfigEntityFixture.resolve_config_entity_fixture(
        config_entity)
    db_entity_filter = dict(key__in=db_entity_keys) if db_entity_keys else {}

    # Process the DbEntities from the origin_instance or the db_entity_configuration from the fixtures,
    # but only the first time this scenario is saved
    # We only get those scoped (owned) by the class of our config_entity. The scoped above will be adopted automatically
    # and need not be created. This means a Scenario creates DbEntities scoped to Scenario and adopts those scoped
    # to Project or Region. It does not clone the latter.
    if CrudKey.CLONE == crud:
        # CRUD the DbEntities to match the origin instance
        origin_instance = config_entity.origin_instance
        # Clone the DbEntities from the origin ConfigEntity.
        db_entities = map(
            lambda source_db_entity: clone_or_update_db_entity_and_interest(
                config_entity, source_db_entity,
                DbEntity(schema=config_entity.schema(),
                         feature_class_configuration=FeatureClassConfiguration(
                             geography_scope=FeatureClassCreator(
                                 config_entity).resolved_geography_scope.id,
                             class_attrs={
                                 'config_entity__id': config_entity.id,
                                 'override_db': config_entity.db,
                                 'db_entity_key': source_db_entity.key
                             }))).db_entity,
            origin_instance.owned_db_entities(**db_entity_filter))
    elif crud in [CrudKey.SYNC, CrudKey.CREATE]:
        #TODO examine the two conditions below more carefully. We want syncing to be the same for clones and non-clones
        if config_entity.origin_instance:
            # Syncing previously cloned instance
            db_entities = config_entity.owned_db_entities(**db_entity_filter)
            update_or_create_db_entities_and_interests(config_entity,
                                                       *db_entities)
        else:
            # Create or Sync new instance
            # Get the default DbEntity configurations from the fixture
            default_db_entities = filter(
                lambda db_entity: db_entity.key in db_entity_keys
                if db_entity_keys else True,
                client_fixture.default_db_entities())
            # Find additional owned (not adopted) db_entities that aren't defaults, namely those that were created by the user
            additional_db_entities = filter(
                lambda db_entity: db_entity.key in db_entity_keys
                if db_entity_keys else True,
                client_fixture.non_default_owned_db_entities())
            # Combine the defaults with the additions
            db_entities = default_db_entities + list(additional_db_entities)
            update_or_create_db_entities_and_interests(config_entity,
                                                       *db_entities)
    elif CrudKey.UPDATE == crud:
        # No complex updates are enabled for scenarios, so no post-save processing is needed
        return
    elif CrudKey.DELETE == crud:
        raise NotImplementedError("DELETE is not implemented")

    # Disable the post_post_save signal while saving to prevent an infinite loop
    previous = config_entity._no_post_save_publishing
    config_entity._no_post_save_publishing = True
    # Save post_create changes. This is just to store selected DbEntities
    config_entity.save()
    config_entity._no_post_save_publishing = previous

    reset_queries()
Beispiel #13
0
def on_db_entity_interest_post_save(sender, **kwargs):
    """
        Called after a DbEntityInterest saves, but not when a config_entity is running post_save publishers
        In other words, this is only called after a direct DbEntityInterest save/update.
        This does the same as post_save_config_entity, but starts with the 'post_save_config_entity_db_entities'
        signal to do only DbEntity dependent presentation.
    """
    db_entity_interest = kwargs['instance']
    config_entity = ConfigEntity._subclassed(db_entity_interest.config_entity)
    db_entity = db_entity_interest.db_entity
    # TODO The default user should be the admin
    user = db_entity.updater if db_entity.updater else get_user_model(
    ).objects.get(username=UserGroupKey.SUPERADMIN)
    # post_save_db_entity presentation should always be disabled if we are saving a ConfigEntity
    logger.info(
        "Handler: post_save_db_entity_interest for config_entity {config_entity}, db_entity {db_entity}, "
        "and user {username}.".format(config_entity=config_entity,
                                      db_entity=db_entity_interest.db_entity,
                                      username=user.username))

    if kwargs.get('created', None):
        db_entity = db_entity_interest.db_entity
        # TODO
        # While we test upload, just delete the previous DbEntitys with the same key name
        # in the ConfigEntity.
        db_entity_interest.config_entity.db_entities.filter(
            key=db_entity.key).exclude(id=db_entity.id).delete()

        # Make sure the db_entity's schema matches the config_entity's if not set
        # TODO we assume that the schema should match the config_entity, rather than
        # an ancestor or the config_entity (like the project or a scenario). There
        # are many cases where the schema should not be that of the config_entity, so
        # we might want to remove this default and force the saver to set it
        if not db_entity.schema or not db_entity.table:
            db_entity.schema = db_entity.schema or db_entity_interest.config_entity.schema(
            )
            # Always base the table name on the key
            db_entity.table = db_entity.key
            db_entity_interest.db_entity.save()

    if db_entity_interest.config_entity.deleted:
        # Do nothing for deleted config_entities
        return

    # Define the data_importer if not already set
    if not (db_entity.feature_class_configuration
            and db_entity.feature_class_configuration.data_importer):
        feature_class_configuration = db_entity.feature_class_configuration = db_entity.feature_class_configuration or FeatureClassConfiguration(
        )
        # Choose the correct importer, if any, to set up the feature_class_configuration and features
        if db_entity.origin_instance:
            # Import from the origin_instance. This could be a full copy or from the current layer selection features
            feature_class_configuration.data_importer = full_module_path(
                OriginDbEntityProcessor)
        elif '.json' in db_entity.url.lower():
            # Import it using the geojson importer
            feature_class_configuration.data_importer = full_module_path(
                GeoJsonProcessor)
            # Indicate that the feature class configuration was generated not fixture based
            feature_class_configuration.generated = True
        elif '.zip' in db_entity.url.lower():
            feature_class_configuration.data_importer = full_module_path(
                ZippedSqlFileProcessor)
            # Indicate that the feature class configuration was generated not fixture based
            feature_class_configuration.generated = True
        elif not db_entity.no_feature_class_configuration:
            feature_class_configuration.data_importer = full_module_path(
                DefaultImportProcessor)
        previous = DbEntityInterest._no_post_save_publishing
        DbEntityInterest._no_post_save_publishing = True
        db_entity.feature_class_configuration = feature_class_configuration
        db_entity.save()
        DbEntityInterest._no_post_save_publishing = previous

    # Post save presentation section
    # Quit if the publishers were turned off outside this method
    if DbEntityInterest._no_post_save_publishing or db_entity_interest._no_post_save_publishing:
        return

    # Use this to initialize the FeatureBehavior and other stuff that might not be set
    update_or_create_db_entity(config_entity, db_entity)

    starting_signal_path = resolvable_module_attr_path(
        __name__, 'post_save_db_entity_initial')

    return post_save_publishing(
        starting_signal_path,
        config_entity,
        user,
        instance=db_entity_interest,
        instance_class=DbEntity,
        client_instance_path='db_entity',
        instance_key=db_entity_interest.db_entity.key,
        signal_proportion_lookup=signal_proportion_lookup,
        dependent_signal_paths=dependent_signal_paths,
        signal_prefix='post_save_db_entity',
        # Update the setup_percent_complete instance attribute for new instances
        # of classes with this attribute (currently only DbEntity)
        update_setup_percent_complete=db_entity_interest.db_entity.
        setup_percent_complete == 0,
        **filter_keys(kwargs, ['created']))