示例#1
0
class AdminBoundary(MPTTModel, models.Model):
    """
    Represents a single administrative boundary (like a country, state or district)
    """
    osm_id = models.CharField(max_length=15, unique=True,
                              help_text="This is the OSM id for this administrative boundary")

    name = models.CharField(max_length=128,
                            help_text="The name of our administrative boundary")

    level = models.IntegerField(help_text="The level of the boundary, 0 for country, 1 for state, 2 for district, 3 for ward")

    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True,
                            help_text="The parent to this political boundary if any")

    geometry = models.MultiPolygonField(null=True,
                                        help_text="The full geometry of this administrative boundary")

    simplified_geometry = models.MultiPolygonField(null=True,
                                                   help_text="The simplified geometry of this administrative boundary")

    objects = models.GeoManager()

    @staticmethod
    def get_geojson_dump(features):
        # build a feature collection
        feature_collection = geojson.FeatureCollection(features)
        return geojson.dumps(feature_collection)

    def as_json(self):
        result = dict(osm_id=self.osm_id, name=self.name,
                      level=self.level, aliases='')

        if self.parent:
            result['parent_osm_id'] = self.parent.osm_id

        aliases = '\n'.join([alias.name for alias in self.aliases.all()])
        result['aliases'] = aliases
        return result

    def get_geojson_feature(self):
        return geojson.Feature(properties=dict(name=self.name, osm_id=self.osm_id, id=self.pk, level=self.level),
                               zoomable=True if self.children.all() else False,
                               geometry=None if not self.simplified_geometry else geojson.loads(self.simplified_geometry.geojson))

    def get_geojson(self):
        return AdminBoundary.get_geojson_dump([self.get_geojson_feature()])

    def get_children_geojson(self):
        children = []
        for child in self.children.all():
            children.append(child.get_geojson_feature())
        return AdminBoundary.get_geojson_dump(children)

    def update(self, **kwargs):
        AdminBoundary.objects.filter(id=self.id).update(**kwargs)

        # if our name changed, update the category on any of our values
        name = kwargs.get('name', self.name)
        if name != self.name:
            from temba.values.models import Value
            Value.objects.filter(location_value=self).update(category=name)

        # update our object values so that self is up to date
        for key, value in kwargs.items():
            setattr(self, key, value)

    def __str__(self):
        return "%s" % self.name
示例#2
0
class Person(models.Model):
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
    #  Jards Macalé is an amazing brazilian musician! =]
    enjoy_jards_macale = models.BooleanField(default=True)
    like_metal_music = models.BooleanField(default=False)
    name = models.CharField(max_length=30)
    nickname = models.SlugField(max_length=36)
    age = models.IntegerField()
    bio = models.TextField()
    birthday = models.DateField()
    birth_time = models.TimeField()
    appointment = models.DateTimeField()
    blog = models.URLField()
    occupation = models.CharField(max_length=10, choices=OCCUPATION_CHOICES)
    uuid = models.UUIDField(primary_key=False)
    name_hash = models.BinaryField(max_length=16)
    days_since_last_login = models.BigIntegerField()
    duration_of_sleep = models.DurationField()
    email = models.EmailField()
    id_document = models.CharField(unique=True, max_length=10)

    try:
        from django.db.models import JSONField

        data = JSONField()
    except ImportError:
        # Skip JSONField-related fields
        pass

    try:
        from django.contrib.postgres.fields import ArrayField, HStoreField
        from django.contrib.postgres.fields import JSONField as PostgresJSONField
        from django.contrib.postgres.fields.citext import (
            CICharField,
            CIEmailField,
            CITextField,
        )
        from django.contrib.postgres.fields.ranges import (
            BigIntegerRangeField,
            DateRangeField,
            DateTimeRangeField,
            IntegerRangeField,
        )

        if settings.USING_POSTGRES:
            acquaintances = ArrayField(models.IntegerField())
            postgres_data = PostgresJSONField()
            hstore_data = HStoreField()
            ci_char = CICharField(max_length=30)
            ci_email = CIEmailField()
            ci_text = CITextField()
            int_range = IntegerRangeField()
            bigint_range = BigIntegerRangeField()
            date_range = DateRangeField()
            datetime_range = DateTimeRangeField()
    except ImportError:
        # Skip PostgreSQL-related fields
        pass

    try:
        from django.contrib.postgres.fields.ranges import FloatRangeField

        if settings.USING_POSTGRES:
            float_range = FloatRangeField()
    except ImportError:
        # Django version greater or equal than 3.1
        pass

    try:
        from django.contrib.postgres.fields.ranges import DecimalRangeField

        if settings.USING_POSTGRES:
            decimal_range = DecimalRangeField()
    except ImportError:
        # Django version lower than 2.2
        pass

    if BAKER_GIS:
        geom = models.GeometryField()
        point = models.PointField()
        line_string = models.LineStringField()
        polygon = models.PolygonField()
        multi_point = models.MultiPointField()
        multi_line_string = models.MultiLineStringField()
        multi_polygon = models.MultiPolygonField()
        geom_collection = models.GeometryCollectionField()
示例#3
0
class County(models.Model):
    name = models.CharField(max_length=25)
    state = models.ForeignKey(State)
    mpoly = models.MultiPolygonField(srid=4269)  # Multipolygon in NAD83
    objects = models.GeoManager()
示例#4
0
class UserGeometryData(AbstractGeoManager):
    """holds user uploaded geometries"""
    gid = models.IntegerField(null=True)
    user_meta = models.ForeignKey(UserGeometryMetadata)
    desc = models.TextField(blank=True)
    geom = models.MultiPolygonField(srid=4326)

    @property
    def vertex_count(self):
        '''Return a count of the vertices for the geometry'''
        return self.geom.num_points

    def pathLocations(self, color='0x0000ff', weight=4, threshold=0.01):
        '''Returns a list of Google Maps Static API path Location strings for the geometry
        
        Note that only the first 2 dimensions of vertices are returned and they
        are ordered (lat,lon).
        
        Ref: http://code.google.com/apis/maps/documentation/staticmaps/#Paths
        '''
        from contrib.glineenc.glineenc import encode_pairs

        geom = self.geom
        url = [
            '&'.join(  # join multiple polygons
                [
                    'path=color:{color}|weight:{weight}|enc:{encoded_data}'.
                    format(color=color,
                           weight=weight,
                           encoded_data=encode_pairs(
                               points=tuple(
                                   [tuple(reversed(i)) for i in polygon]),
                               threshold=threshold,
                           )[0]) for polygon in multipolygon
                ]) for multipolygon in geom.coords
        ]

        return url

    def geom_gmap_static_url(
        self,
        color='0x0000ff',
        weight=4,
        width=512,
        height=256,
    ):
        '''Returns a Google Maps Static API URL representation of the geometry
        
        Refs:
          http://code.google.com/apis/maps/documentation/staticmaps/#Paths
          http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
        '''
        MAX_PATH_LENGTH = 1930

        # estimate the simplification threshold based on the number of vertices
        if self.vertex_count < 250:
            threshold = 0  # no simplification


#        elif self.vertex_count < 500:
#            threshold = 0.05
        elif self.vertex_count < 2000:
            threshold = 0.05
        else:
            threshold = 0.4

        path_list = self.pathLocations(color=color,
                                       weight=weight,
                                       threshold=threshold)
        # sort so the geometries with the most vertices are first
        path_list.sort(key=len, reverse=True)
        pathLocations = ''
        for path in path_list:
            if len(pathLocations) < MAX_PATH_LENGTH:
                pathLocations += '&{path}'.format(path=path)

        url = ('http://maps.googleapis.com/maps/api/staticmap'
               '?size={width}x{height}'
               '&sensor=false'
               '{pathLocations}').format(
                   color=color,
                   weight=weight,
                   width=width,
                   height=height,
                   pathLocations=pathLocations,
               )
        return url
示例#5
0
class CBSBuurt(models.Model):
    ogc_fid = models.AutoField(primary_key=True)
    bu_code = models.CharField(max_length=10, blank=True, null=True)
    bu_naam = models.CharField(max_length=60, blank=True, null=True)
    wk_code = models.CharField(max_length=8, blank=True, null=True)
    gm_code = models.CharField(max_length=6, blank=True, null=True)
    gm_naam = models.CharField(max_length=60, blank=True, null=True)
    ind_wbi = models.DecimalField(max_digits=10,
                                  decimal_places=0,
                                  blank=True,
                                  null=True)
    water = models.CharField(max_length=4, blank=True, null=True)
    postcode = models.CharField(max_length=10, blank=True, null=True)
    dek_perc = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    oad = models.DecimalField(max_digits=10,
                              decimal_places=0,
                              blank=True,
                              null=True)
    sted = models.DecimalField(max_digits=10,
                               decimal_places=0,
                               blank=True,
                               null=True)
    aant_inw = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    aant_man = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    aant_vrouw = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_00_14_jr = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_15_24_jr = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_25_44_jr = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_45_64_jr = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_65_eo_jr = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_ongehuwd = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_gehuwd = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    p_gescheid = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    p_verweduw = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    bev_dichth = models.DecimalField(max_digits=10,
                                     decimal_places=0,
                                     blank=True,
                                     null=True)
    aantal_hh = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_eenp_hh = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_hh_z_k = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    p_hh_m_k = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    gem_hh_gr = models.DecimalField(max_digits=11,
                                    decimal_places=1,
                                    blank=True,
                                    null=True)
    p_west_al = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_n_w_al = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    p_marokko = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_ant_aru = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_surinam = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_turkije = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    p_over_nw = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    opp_tot = models.DecimalField(max_digits=10,
                                  decimal_places=0,
                                  blank=True,
                                  null=True)
    opp_land = models.DecimalField(max_digits=10,
                                   decimal_places=0,
                                   blank=True,
                                   null=True)
    opp_water = models.DecimalField(max_digits=10,
                                    decimal_places=0,
                                    blank=True,
                                    null=True)
    wkb_geometry = models.MultiPolygonField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'gas_cbs_buurt_2017_raw'
        verbose_name = 'CBS buurt'
        verbose_name_plural = 'CBS buurten'

    def __str__(self):
        if self.bu_naam:
            return '{} - {}'.format(self.bu_naam, self.bu_code)
        else:
            return '{}'.format(self.bu_code)
示例#6
0
class Job(TimeStampedModelMixin):
    """
    Model for a Job.
    """
    def __init__(self, *args, **kwargs):
        kwargs['the_geom'] = convert_polygon(kwargs.get('the_geom')) or ''
        kwargs['the_geom_webmercator'] = convert_polygon(
            kwargs.get('the_geom_webmercator')) or ''
        kwargs['the_geog'] = convert_polygon(kwargs.get('the_geog')) or ''
        super(Job, self).__init__(*args, **kwargs)

    id = models.AutoField(primary_key=True, editable=False)
    uid = models.UUIDField(unique=True,
                           default=uuid.uuid4,
                           editable=False,
                           db_index=True)
    user = models.ForeignKey(User, related_name='owner')
    name = models.CharField(max_length=100, db_index=True)
    description = models.CharField(max_length=1000, db_index=True)
    event = models.CharField(max_length=100,
                             db_index=True,
                             default='',
                             blank=True)
    region = models.ForeignKey(Region, null=True, on_delete=models.SET_NULL)
    provider_tasks = models.ManyToManyField(ProviderTask,
                                            related_name='provider_tasks')
    configs = models.ManyToManyField(ExportConfig,
                                     related_name='configs',
                                     blank=True)
    published = models.BooleanField(default=False,
                                    db_index=True)  # publish export
    feature_save = models.BooleanField(
        default=False, db_index=True)  # save feature selections
    feature_pub = models.BooleanField(
        default=False, db_index=True)  # publish feature selections
    the_geom = models.MultiPolygonField(verbose_name='Extent for export',
                                        srid=4326,
                                        default='')
    the_geom_webmercator = models.MultiPolygonField(
        verbose_name='Mercator extent for export', srid=3857, default='')
    the_geog = models.MultiPolygonField(
        verbose_name='Geographic extent for export',
        geography=True,
        default='')
    objects = models.GeoManager()
    include_zipfile = models.BooleanField(default=False)
    json_tags = JSONField(default=dict)

    class Meta:  # pragma: no cover
        managed = True
        db_table = 'jobs'

    def save(self, *args, **kwargs):
        self.the_geom = convert_polygon(self.the_geom)
        self.the_geog = GEOSGeometry(self.the_geom)
        self.the_geom_webmercator = self.the_geom.transform(ct=3857,
                                                            clone=True)
        super(Job, self).save(*args, **kwargs)

    def __str__(self):
        return '{0}'.format(self.name)

    @property
    def overpass_extents(self, ):
        """
        Return the export extents in order required by Overpass API.
        """
        extents = GEOSGeometry(self.the_geom).extent  # (w,s,e,n)
        # overpass needs extents in order (s,w,n,e)
        overpass_extents = '{0},{1},{2},{3}'.format(str(extents[1]),
                                                    str(extents[0]),
                                                    str(extents[3]),
                                                    str(extents[2]))
        return overpass_extents

    @property
    def extents(self, ):
        return GEOSGeometry(self.the_geom).extent  # (w,s,e,n)

    @property
    def filters(self, ):
        """
        Return key=value pairs for each tag in this export.

        Used in utils.overpass.filter to filter the export.
        """
        # Command-line key=value filters for osmfilter
        filters = []
        for tag in self.json_tags:
            kv = '{0}={1}'.format(tag['key'], tag['value'])
            filters.append(kv)
        return filters

    @property
    def categorised_tags(self, ):
        """
        Return tags mapped according to their geometry types.
        """
        points = set()
        lines = set()
        polygons = set()
        for tag in self.json_tags:
            if 'point' in tag['geom']:
                points.add(tag['key'])
            if 'line' in tag['geom']:
                lines.add(tag['key'])
            if 'polygon' in tag['geom']:
                polygons.add(tag['key'])
        return {
            'points': sorted(list(points)),
            'lines': sorted(list(lines)),
            'polygons': sorted(list(polygons))
        }

    @property
    def bounds_geojson(self, ):
        return serialize('geojson', [self],
                         geometry_field='the_geom',
                         fields=('name', 'the_geom'))
示例#7
0
class DataProvider(UIDMixin, TimeStampedModelMixin, CachedModelMixin):
    """
    Model for a DataProvider.
    """

    name = models.CharField(verbose_name="Service Name",
                            unique=True,
                            max_length=100)

    slug = LowerCaseCharField(max_length=40, unique=True, default="")
    label = models.CharField(verbose_name="Label",
                             max_length=100,
                             null=True,
                             blank=True)
    url = models.CharField(
        verbose_name="Service URL",
        max_length=1000,
        null=True,
        default="",
        blank=True,
        help_text=
        "The SERVICE_URL is used as the endpoint for WFS, OSM, and WCS services. It is "
        "also used to check availability for all OGC services. If you are adding a TMS "
        "service, please provide a link to a single tile, but with the coordinate numbers "
        "replaced by {z}, {y}, and {x}. Example: https://tiles.your-geospatial-site.com/"
        "tiles/default/{z}/{y}/{x}.png",
    )
    preview_url = models.CharField(
        verbose_name="Preview URL",
        max_length=1000,
        null=True,
        default="",
        blank=True,
        help_text=
        "This url will be served to the front end for displaying in the map.",
    )
    service_copyright = models.CharField(
        verbose_name="Copyright",
        max_length=2000,
        null=True,
        default="",
        blank=True,
        help_text=
        "This information is used to display relevant copyright information.",
    )
    service_description = models.TextField(
        verbose_name="Description",
        null=True,
        default="",
        blank=True,
        help_text=
        "This information is used to provide information about the service.",
    )
    layer = models.CharField(verbose_name="Service Layer",
                             max_length=100,
                             null=True,
                             blank=True)
    export_provider_type = models.ForeignKey(DataProviderType,
                                             verbose_name="Service Type",
                                             null=True,
                                             on_delete=models.CASCADE)
    max_selection = models.DecimalField(
        verbose_name="Max selection area",
        default=250,
        max_digits=12,
        decimal_places=3,
        help_text=
        "This is the maximum area in square kilometers that can be exported "
        "from this provider in a single DataPack.",
    )
    level_from = models.IntegerField(
        verbose_name="Seed from level",
        default=0,
        null=True,
        blank=True,
        help_text=
        "This determines the starting zoom level the tile export will seed from.",
    )
    level_to = models.IntegerField(
        verbose_name="Seed to level",
        default=10,
        null=True,
        blank=True,
        help_text=
        "This determines the highest zoom level the tile export will seed to.",
    )
    config = models.TextField(
        default="",
        null=True,
        blank=True,
        verbose_name="Configuration",
        help_text=
        """WMS, TMS, WMTS, and ArcGIS-Raster require a MapProxy YAML configuration
                              with a Sources key of imagery and a Service Layer name of imagery; the validator also
                              requires a layers section, but this isn't used.
                              OSM Services also require a YAML configuration.""",
    )

    DATA_TYPES = [
        (GeospatialDataType.VECTOR.value, ("Vector")),
        (GeospatialDataType.RASTER.value, ("Raster")),
        (GeospatialDataType.ELEVATION.value, ("Elevation")),
        (GeospatialDataType.MESH.value, ("Mesh")),
        (GeospatialDataType.POINT_CLOUD.value, ("Point Cloud")),
    ]
    data_type = models.CharField(
        choices=DATA_TYPES,
        max_length=20,
        verbose_name="Data Type",
        null=True,
        default="",
        blank=True,
        help_text="The type of data provided (e.g. elevation, raster, vector)",
    )
    user = models.ForeignKey(User,
                             related_name="+",
                             null=True,
                             default=None,
                             blank=True,
                             on_delete=models.CASCADE)
    license = models.ForeignKey(License,
                                related_name="+",
                                null=True,
                                blank=True,
                                default=None,
                                on_delete=models.CASCADE)

    zip = models.BooleanField(default=False)
    display = models.BooleanField(default=False)
    thumbnail = models.ForeignKey(
        MapImageSnapshot,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        help_text="A thumbnail image generated to give a high level"
        " preview of what a provider's data looks like.",
    )
    attribute_class = models.ForeignKey(
        AttributeClass,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name="data_providers",
        help_text=
        "The attribute class is used to limit users access to resources using this data provider.",
    )
    the_geom = models.MultiPolygonField(
        verbose_name="Covered Area",
        srid=4326,
        default=
        "SRID=4326;MultiPolygon (((-180 -90,180 -90,180 90,-180 90,-180 -90)))",
    )

    # Used to store user list of user caches so that they can be invalidated.
    provider_caches_key = "data_provider_caches"

    class Meta:  # pragma: no cover

        managed = True
        db_table = "export_provider"

    # Check if config changed to updated geometry
    __config = None
    __url = None
    __layer = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__config = self.config
        self.__url = self.url
        self.__layer = self.layer

    def update_geom(self):
        from eventkit_cloud.tasks.helpers import download_data
        from eventkit_cloud.ui.helpers import file_to_geojson

        geometry = None
        if self.config != self.__config:
            orig_extent_url = load_provider_config(
                self.__config).get("extent_url")
            config = load_provider_config(self.config)
            extent_url = config.get("extent_url")
            if extent_url and extent_url != orig_extent_url:
                random_uuid = uuid.uuid4()
                session = get_or_update_session(**config)
                if not extent_url:
                    return
                output_file = download_data(task_uid=str(random_uuid),
                                            input_url=extent_url,
                                            session=session)
                geojson = file_to_geojson(output_file)
                geojson_geometry = geojson.get("geometry") or geojson.get(
                    "features", [{}])[0].get("geometry")
                geometry = GEOSGeometry(json.dumps(geojson_geometry),
                                        srid=4326)
        elif (self.url != self.__url) or (self.layer != self.__layer):
            try:
                client = self.get_service_client()
                geometry = client.download_geometry()
            except AttributeError as e:
                # TODO: This fails in tests.  How to handle failure to update geometry?
                logger.info(e, exc_info=True)
        if geometry:
            self.the_geom = convert_polygon(geometry)

    def get_service_client(self) -> GisClient:
        url = self.url
        if not self.url and "osm" in self.export_provider_type.type_name:
            logger.error(
                "Use of settings.OVERPASS_API_URL is deprecated and will be removed in 1.13"
            )
            url = settings.OVERPASS_API_URL
        Client = get_client(self.export_provider_type.type_name)
        return Client(url,
                      self.layer,
                      aoi_geojson=None,
                      slug=self.slug,
                      config=load_provider_config(self.config))

    def check_status(self, aoi_geojson: dict = None):
        try:
            client = self.get_service_client()
            response = client.check(aoi_geojson=aoi_geojson)

        except Exception as e:
            logger.error(e, exc_info=True)
            response = get_status_result(CheckResult.UNKNOWN_ERROR)
            logger.error(
                f"An exception occurred while checking the {self.name} provider.",
                exc_info=True)
            logger.info(f"Status of provider '{self.name}': {response}")

        return response

    def save(self, force_insert=False, force_update=False, *args, **kwargs):
        # Something is closing the database connection which is raising an error.
        # Using a separate process allows the connection to be closed in separate process while leaving it open.
        proc = multiprocessing.dummy.Process(target=self.update_geom)
        proc.start()
        proc.join()

        if not self.slug:
            self.slug = self.name.replace(" ", "_").lower()
            if len(self.slug) > 40:
                self.slug = self.slug[0:39]
        cache.delete(f"base-config-{self.slug}")

        super(DataProvider, self).save(force_insert, force_update, *args,
                                       **kwargs)

    def __str__(self):
        return "{0}".format(self.name)

    @property
    def metadata(self):
        from eventkit_cloud.utils.mapproxy import get_mapproxy_metadata_url

        if not self.config:
            return None
        config = yaml.load(self.config)
        url = config.get("sources", {}).get("info", {}).get("req",
                                                            {}).get("url")
        type = config.get("sources", {}).get("info", {}).get("type")
        if url:
            return {"url": get_mapproxy_metadata_url(self.slug), "type": type}

    @property
    def footprint_url(self):
        from eventkit_cloud.utils.mapproxy import get_mapproxy_footprint_url

        if not self.config:
            return None
        config = yaml.load(self.config)

        url = config.get("sources", {}).get("footprint", {}).get("req",
                                                                 {}).get("url")
        if url:
            return get_mapproxy_footprint_url(self.slug)

    @property
    def layers(self) -> List[str]:
        """
        Used to populate the list of vector layers, typically for contextual or styling information.
        :return: A list of layer names.
        """
        if self.data_type != GeospatialDataType.VECTOR.value:
            return []
        if not self.config:
            # Often layer names are configured using an index number but this number is not very
            # useful when using the data so fall back to the slug which should be more meaningful.
            if not self.layer:  # check for NoneType or empty string
                return [self.slug]
            try:
                int(self.layer)
                return [
                    self.slug
                ]  # self.layer is an integer, so use the slug for better context.
            except ValueError:
                return [
                    self.layer
                ]  # If we got here, layer is not None or an integer so use that.
        config = clean_config(self.config, return_dict=True)
        # As of EK 1.9.0 only vectors support multiple layers in a single provider
        if self.export_provider_type.type_name in ["osm", "osm-generic"]:
            return list(config.keys())
        else:
            return [
                layer.get("name") for layer in config.get("vector_layers", [])
            ]

    def get_use_bbox(self):
        if self.export_provider_type is not None:
            return self.export_provider_type.use_bbox
        else:
            return False

    """
    Max datasize is the size in megabytes.
    """

    @property
    def max_data_size(self):
        config = yaml.load(self.config)
        return None if config is None else config.get("max_data_size", None)

    def get_max_data_size(self, user=None):

        if not user:
            return self.max_data_size

        # the usersizerule set is looped instead of using a queryset filter so that it can be prefetched.
        if user:
            user_size_rule = list(
                filter(lambda user_size_rule: user_size_rule.user == user,
                       self.usersizerule_set.all()))
            if user_size_rule:
                return user_size_rule[0].max_data_size

        return self.max_data_size

    def get_max_selection_size(self, user=None):

        if not user:
            return self.max_selection

        # the usersizerule set is looped instead of using a queryset filter so that it can be prefetched.
        if user:
            user_size_rule = list(
                filter(lambda user_size_rule: user_size_rule.user == user,
                       self.usersizerule_set.all()))
            if user_size_rule:
                return user_size_rule[0].max_selection_size

        return self.max_selection

    def get_data_type(self) -> str:
        """
        This is used to populate the run metadata with special types for OSM and NOME.
        This is used for custom cartography,
        and should be removed if custom cartography is made configurable.
        :param data_provider:
        :return:
        """
        if self.slug.lower() in ["nome", "osm"]:
            return self.slug.lower()
        else:
            return str(self.data_type)
示例#8
0
class WalkInAccess(models.Model):
    unit_number = models.IntegerField()
    land_type = models.IntegerField()
    polygon = models.MultiPolygonField()
    center_point = models.PolygonField()
    square_feet = models.FloatField(default=0.0)
示例#9
0
class UserData(gismodels.Model):
    user_shape = models.ForeignKey("geodata.UserProjectShape",
                                   on_delete=models.CASCADE)
    geometry = gismodels.MultiPolygonField(srid=4326)
示例#10
0
class TimeZone(models.Model):
    objects = models.Manager()

    name = models.CharField(max_length=256)
    bounds = models.MultiPolygonField(blank=True, null=True)
示例#11
0
class PhoneAreaCode(models.Model):
    objects = models.Manager()

    name = models.CharField(max_length=256)
    bounds = models.MultiPolygonField(blank=True, null=True)
    center = models.PointField(blank=True, null=True)
示例#12
0
class Region(MPTTModel, gismodels.Model):
    name = models.CharField(
        max_length=50,
        unique=True,
        verbose_name='Название',
    )
    short_name = models.CharField(max_length=150,
                                  unique=True,
                                  verbose_name='Сокращенное название')
    slug_name = models.SlugField(
        max_length=100,
        unique=True,
        verbose_name='Идентификатор',
    )
    parent = TreeForeignKey(
        'self',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='children',
        verbose_name='Входит в',
    )
    borders = gismodels.MultiPolygonField(
        srid=4326,
        null=True,
        blank=True,
        verbose_name='границы региона',
    )

    map_center = gismodels.PointField(
        srid=4326,
        null=True,
        blank=True,
        verbose_name='центр карты',
    )

    geojson_file = models.FileField(
        upload_to=region_directory_path,
        blank=True,
        null=True,
        verbose_name='geojson файл границ региона',
    )

    def save(self, *args, **kwargs):
        if file_exists(self.geojson_file):
            with self.geojson_file.open(mode='r') as file_handler:
                borders = file_handler.read()
                self.borders = borders

        # if self.geojson_file and file_exists(self.geojson_file):
        #     self.geojson_file.open(mode='rb')

        if self.borders:
            regions = Region.objects.annotate(center=Centroid('borders'))
            self.map_center = regions.get(pk=self.pk).center

        super().save(*args, **kwargs)

    def __str__(self):
        return self.name

    class MPTTMeta:
        order_insertion_by = ['name']

    class Meta:
        verbose_name = 'Регион'
        verbose_name_plural = 'Регион'
示例#13
0
class County(NamedModel):
    state = models.ForeignKey(State, models.CASCADE)
    mpoly = models.MultiPolygonField(srid=4269)  # Multipolygon in NAD83
示例#14
0
class Territorio(models.Model):
    TERRITORIO = Choices(
        ('C', 'Comune'),
        ('P', 'Provincia'),
        ('R', 'Regione'),
        ('N', 'Nazionale'),
        ('E', 'Estero'),
    )

    cod_reg = models.IntegerField(default=0,
                                  blank=True,
                                  null=True,
                                  db_index=True)
    cod_prov = models.IntegerField(default=0,
                                   blank=True,
                                   null=True,
                                   db_index=True)
    cod_com = models.IntegerField(default=0,
                                  blank=True,
                                  null=True,
                                  db_index=True)
    denominazione = models.CharField(max_length=128, db_index=True)
    denominazione_ted = models.CharField(max_length=128,
                                         blank=True,
                                         null=True,
                                         db_index=True)
    slug = AutoSlugField(populate_from='nome_per_slug',
                         max_length=256,
                         unique=True,
                         db_index=True)
    territorio = models.CharField(max_length=1,
                                  choices=TERRITORIO,
                                  db_index=True)
    geom = models.MultiPolygonField(srid=4326, null=True, blank=True)
    popolazione_totale = models.IntegerField(null=True, blank=True)
    popolazione_maschile = models.IntegerField(null=True, blank=True)
    popolazione_femminile = models.IntegerField(null=True, blank=True)

    objects = TerritorioManager()

    @property
    def nome(self):
        if self.denominazione_ted:
            return u'{} - {}'.format(self.denominazione,
                                     self.denominazione_ted)
        else:
            return u'{}'.format(self.denominazione)

    @property
    def nome_completo(self):
        if self.is_comune or self.is_provincia:
            return u'{} di {}'.format(self.get_territorio_display(), self.nome)
        elif self.is_regione:
            return u'{} {}'.format(self.get_territorio_display(), self.nome)
        else:
            return u'{}'.format(self.nome)

    @property
    def nome_con_provincia(self):
        if self.is_provincia:
            return u'{} (Provincia)'.format(self.nome)
        else:
            return u'{}'.format(self.nome)

    @property
    def nome_per_slug(self):
        return u'{} {}'.format(self.denominazione,
                               self.get_territorio_display())

    @property
    def ambito_territoriale(self):
        """
        Returns: a Region (for C,P or R), Nazionale, or Estero
        """
        if self.is_regione:
            return self.nome
        elif self.regione:
            return self.regione.nome
        else:
            return self.get_territorio_display()

    @cached_property
    def regione(self):
        if self.is_comune or self.is_provincia:
            return self.__class__.objects.regioni_by_cod[self.cod_reg]
        else:
            return None

    @cached_property
    def provincia(self):
        if self.is_comune:
            return self.__class__.objects.provincie_by_cod[self.cod_prov]
        else:
            return None

    @property
    def codice(self):
        if self.is_comune:
            return self.cod_com
        elif self.is_provincia:
            return self.cod_prov
        else:
            return self.cod_reg

    def progetti(self):
        return self.progetto_set.all()

    @property
    def n_progetti(self):
        return self.progetto_set.count()

    @property
    def code(self):
        return self.get_cod_dict().values()[0]

    def get_cod_dict(self, prefix=''):
        """
        Return a dict with {prefix}cod_{type} key initialized with correct value
        """
        if self.is_comune:
            return {'{}cod_com'.format(prefix): self.cod_com}
        elif self.is_provincia:
            return {'{}cod_prov'.format(prefix): self.cod_prov}
        elif self.is_regione:
            return {'{}cod_reg'.format(prefix): self.cod_reg}
        elif self.is_nazionale:
            return {'{}cod_reg'.format(prefix): 0}
        elif self.is_estero:
            return {'{}pk'.format(prefix): self.pk}

        raise Exception('Territorio non interrogabile {}'.format(self))

    def get_progetti_search_url(self, **kwargs):
        """
        Returns the correct search url in progetti faceted navigation.
        Can be used with optional filters:
        tema=TemaInstance
        natura=ClassificazioneAzioneInstance
        """
        search_url = reverse('progetti_search') + '?q='

        if 'tema' in kwargs:
            tema = kwargs['tema']
            search_url += '&selected_facets=tema:{}'.format(tema.codice)

        if 'natura' in kwargs:
            natura = kwargs['natura']
            search_url += '&selected_facets=natura:{}'.format(natura.codice)

        if 'programma' in kwargs:
            programma = kwargs['programma']
            search_url += '&fonte_fin={}'.format(programma.codice)

        if 'gruppo_programmi' in kwargs:
            gruppo_programmi = kwargs['gruppo_programmi']
            search_url += '&gruppo_programmi={}'.format(
                gruppo_programmi.codice)

        d = self.get_cod_dict()
        key = d.keys()[0]
        search_url += '&territorio{}={}'.format(key[3:], d[key])

        return search_url

    def get_absolute_url(self):
        url_name = 'territori_{}'.format(self.get_territorio_display().lower())

        if self.is_nazionale or self.is_estero:
            return reverse(url_name)
        else:
            return reverse(url_name, kwargs={'slug': self.slug})

    def __getattr__(self, item):
        match = re.search(
            '^is_({})$'.format('|'.join(
                dict(self.__class__.TERRITORIO).values()).lower()), item)
        if match:
            return self.get_territorio_display().lower() == match.group(1)
        else:
            raise AttributeError('{0!r} object has no attribute {1!r}'.format(
                self.__class__.__name__, item))

    def __unicode__(self):
        return u'{}'.format(self.nome)

    class Meta:
        verbose_name = u'Località'
        verbose_name_plural = u'Località'
        ordering = ['denominazione']
示例#15
0
from django.contrib.gis.db import models
from django.db import connection, migrations

ops = [
    migrations.CreateModel(
        name='Neighborhood',
        fields=[
            ('id',
             models.AutoField(verbose_name='ID',
                              serialize=False,
                              auto_created=True,
                              primary_key=True)),
            ('name', models.CharField(max_length=100, unique=True)),
            ('geom', models.MultiPolygonField(srid=4326)),
        ],
        options={},
        bases=(models.Model, ),
    ),
    migrations.CreateModel(
        name='Household',
        fields=[
            ('id',
             models.AutoField(verbose_name='ID',
                              serialize=False,
                              auto_created=True,
                              primary_key=True)),
            ('neighborhood',
             models.ForeignKey(
                 'gis_migrations.Neighborhood',
                 models.SET_NULL,
                 to_field='id',
示例#16
0
class AdminBoundary(MPTTModel, models.Model):
    """
    Represents a single administrative boundary (like a country, state or district)
    """

    LEVEL_COUNTRY = 0
    LEVEL_STATE = 1
    LEVEL_DISTRICT = 2
    LEVEL_WARD = 3

    # used to separate segments in a hierarchy of boundaries. Has the advantage of being a character in GSM7 and
    # being very unlikely to show up in an admin boundary name.
    PATH_SEPARATOR = ">"
    PADDED_PATH_SEPARATOR = " > "

    osm_id = models.CharField(
        max_length=15, unique=True, help_text="This is the OSM id for this administrative boundary"
    )

    name = models.CharField(max_length=128, help_text="The name of our administrative boundary")

    level = models.IntegerField(
        help_text="The level of the boundary, 0 for country, 1 for state, 2 for district, 3 for ward"
    )

    parent = TreeForeignKey(
        "self",
        null=True,
        on_delete=models.PROTECT,
        blank=True,
        related_name="children",
        db_index=True,
        help_text="The parent to this political boundary if any",
    )

    path = models.CharField(max_length=768, help_text="The full path name for this location")

    geometry = models.MultiPolygonField(null=True, help_text="The full geometry of this administrative boundary")

    simplified_geometry = models.MultiPolygonField(
        null=True, help_text="The simplified geometry of this administrative boundary"
    )

    objects = NoGeometryManager()
    geometries = GeometryManager()

    @staticmethod
    def get_geojson_dump(features):
        # build a feature collection
        feature_collection = geojson.FeatureCollection(features)
        return geojson.dumps(feature_collection)

    def as_json(self):
        result = dict(osm_id=self.osm_id, name=self.name, level=self.level, aliases="")

        if self.parent:
            result["parent_osm_id"] = self.parent.osm_id

        aliases = "\n".join([alias.name for alias in self.aliases.all()])
        result["aliases"] = aliases
        return result

    def get_geojson_feature(self):
        return geojson.Feature(
            properties=dict(name=self.name, osm_id=self.osm_id, id=self.pk, level=self.level),
            zoomable=True if self.children.all() else False,
            geometry=None if not self.simplified_geometry else geojson.loads(self.simplified_geometry.geojson),
        )

    def get_geojson(self):
        return AdminBoundary.get_geojson_dump([self.get_geojson_feature()])

    def get_children_geojson(self):
        children = []
        for child in self.children.all():
            children.append(child.get_geojson_feature())
        return AdminBoundary.get_geojson_dump(children)

    def update(self, **kwargs):
        AdminBoundary.objects.filter(id=self.id).update(**kwargs)

        # update our object values so that self is up to date
        for key, value in kwargs.items():
            setattr(self, key, value)

    def update_path(self):
        if self.level == 0:
            self.path = self.name
            self.save(update_fields=("path",))

        def _update_child_paths(boundary):
            boundaries = AdminBoundary.objects.filter(parent=boundary).only("name", "parent__path")
            boundaries.update(
                path=Concat(Value(boundary.path), Value(" %s " % AdminBoundary.PATH_SEPARATOR), F("name"))
            )
            for boundary in boundaries:
                _update_child_paths(boundary)

        _update_child_paths(self)

    def release(self):
        AdminBoundary.objects.filter(parent=self).update(parent=None)
        self.delete()

    @classmethod
    def create(cls, osm_id, name, level, parent=None, **kwargs):
        """
        Create method that takes care of creating path based on name and parent
        """
        path = name
        if parent is not None:
            path = parent.path + AdminBoundary.PADDED_PATH_SEPARATOR + name

        return AdminBoundary.objects.create(osm_id=osm_id, name=name, level=level, parent=parent, path=path, **kwargs)

    @classmethod
    def strip_last_path(cls, path):
        """
        Strips the last part of the passed in path. Throws if there is no separator
        """
        parts = path.split(AdminBoundary.PADDED_PATH_SEPARATOR)
        if len(parts) <= 1:  # pragma: no cover
            raise Exception("strip_last_path called without a path to strip")

        return AdminBoundary.PADDED_PATH_SEPARATOR.join(parts[:-1])

    @classmethod
    def get_by_path(cls, org, path):
        cache = getattr(org, "_abs", {})

        if not cache:
            setattr(org, "_abs", cache)

        boundary = cache.get(path)
        if not boundary:
            boundary = AdminBoundary.objects.filter(path=path).first()
            cache[path] = boundary

        return boundary

    def __str__(self):
        return "%s" % self.name
示例#17
0
class ITreeRegion(ITreeRegionAbstract, models.Model):
    code = models.CharField(max_length=40, unique=True)
    geometry = models.MultiPolygonField(srid=3857)

    objects = models.GeoManager()
示例#18
0
文件: models.py 项目: nixworks/etools
class Location(MPTTModel):
    """
    Represents Location, either a point or geospatial object,
    pcode should be unique

    Relates to :model:`locations.GatewayType`
    """

    name = models.CharField(verbose_name=_("Name"), max_length=254)
    gateway = models.ForeignKey(GatewayType, verbose_name=_('Location Type'))
    latitude = models.FloatField(
        verbose_name=_("Latitude"),
        null=True,
        blank=True,
    )
    longitude = models.FloatField(
        verbose_name=_("Longitude"),
        null=True,
        blank=True,
    )
    p_code = models.CharField(
        verbose_name=_("P Code"),
        max_length=32,
        blank=True,
        null=True,
    )

    parent = TreeForeignKey(
        'self',
        verbose_name=_("Parent"),
        null=True,
        blank=True,
        related_name='children',
        db_index=True,
    )
    geom = models.MultiPolygonField(
        verbose_name=_("Geo Point"),
        null=True,
        blank=True,
    )
    point = models.PointField(verbose_name=_("Point"), null=True, blank=True)
    created = AutoCreatedField(_('created'))
    modified = AutoLastModifiedField(_('modified'))

    objects = LocationManager()

    def __str__(self):
        # TODO: Make generic
        return u'{} ({} {}: {})'.format(
            self.name, self.gateway.name,
            'CERD' if self.gateway.name == 'School' else 'PCode',
            self.p_code if self.p_code else '')

    @property
    def geo_point(self):
        return self.point if self.point else self.geom.point_on_surface if self.geom else ""

    @property
    def point_lat_long(self):
        return "Lat: {}, Long: {}".format(self.point.y, self.point.x)

    class Meta:
        unique_together = ('name', 'gateway', 'p_code')
        ordering = ['name']
示例#19
0
class DivisionGeography(models.Model):
    division = models.OneToOneField(OrganisationDivision,
                                    related_name="geography",
                                    on_delete=models.CASCADE)
    geography = models.MultiPolygonField()
    source = models.CharField(blank=True, max_length=255)
示例#20
0
class WeatherWarnings(models.Model):
    """
    Weather Warnings from NOAA
    """
    service_id_warnings = 0
    service_id_watches = 1

    prod_type = models.CharField(max_length=200, null=True, blank=True)
    oid = models.CharField(max_length=38, null=True, blank=True)
    idp_source = models.CharField(max_length=200, null=True, blank=True)
    idp_subset = models.CharField(max_length=200, null=True, blank=True)
    url = models.CharField(max_length=500, null=True, blank=True)
    event = models.CharField(max_length=200, null=True, blank=True)
    wfo = models.CharField(max_length=200, null=True, blank=True)
    warnid = models.CharField(max_length=200, null=False, blank=True)
    phenom = models.CharField(max_length=200, null=True, blank=True)
    sig = models.CharField(max_length=200, null=True, blank=True)
    expiration = models.DateTimeField(null=True, blank=True)
    idp_ingestdate = models.DateTimeField(null=True, blank=True)
    issuance = models.DateTimeField(null=True, blank=True)
    warngeom = models.MultiPolygonField(null=True)

    @classmethod
    def create_warning(cls, warning):
        """
        create a weather warning
        """

        warn = WeatherWarnings(prod_type=warning['prod_type'],
                               url=warning['url'],
                               warngeom=warning['warngeom'],
                               warnid=warning['warnid'])
        warn.save()

        return warn

    @property
    def origin_uri(self):
        """
        This object's URI (from the NOAA map service )
        2017-09-18T01:00:00+00:00 time format
        """
        return 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Forecasts_Guidance_Warnings/watch_warn_adv/MapServer/1/{0}?f=json' \
            .format(self.objectid)

    @classmethod
    def load_warning_data(cls):

        #  sometimes error/empty
        objects = WeatherWarnings.requests_retry_session().get('https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Forecasts_Guidance_Warnings/watch_warn_adv/MapServer/1/query?'
                                                               'where=1=1&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&outFields=*&returnGeometry=false'
                                                               '&returnTrueCurves=false&outSR=&returnIdsOnly=true&returnCountOnly=false&returnZ=false&returnM=false&returnDistinctValues=false&f=json', timeout=25)

        print objects.content

        object_ids = set(json.loads(objects.content)['objectIds'])
        url = 'https://idpgis.ncep.noaa.gov/arcgis/rest/services/NWS_Forecasts_Guidance_Warnings/watch_warn_adv/MapServer/1/{0}?f=json'
        for object in object_ids:
            try:
                obj = WeatherWarnings.requests_retry_session().get(url.format(object), timeout=15)
                obj = json.loads(obj.content)

                data = dict((k.lower(), v) for k, v in obj['feature']['attributes'].iteritems())
                warninggeom = ''
                datapost = {}
                #  Check if warning is already loaded and update as needed
                if WeatherWarnings.objects.filter(warnid=data['warnid']):

                    datapost = WeatherWarnings.objects.filter(warnid=data['warnid'])
                    warningfeature = datapost[0]
                    if data['expiration'] != " ":
                        warningfeature.expiration = date_parse(data['expiration'])

                    if obj['feature'].get('geometry'):
                        poly = map(LinearRing, obj['feature']['geometry']['rings'])
                        warningfeature.warngeom = MultiPolygon(fromstr(str(Polygon(*poly).simplify(0.0001))),)
                        warninggeom = MultiPolygon(fromstr(str(Polygon(*poly))),)

                    warningfeature.issuance = date_parse(data['issuance'])
                    warningfeature.idp_subset = data['idp_subset']

                    print data['warnid'] + " Updated"

                else:

                    datapost['prod_type'] = data['prod_type']
                    datapost['idp_source'] = data['idp_source']
                    datapost['sig'] = data['sig']
                    datapost['wfo'] = data['wfo']
                    datapost['url'] = data['url']
                    datapost['phenom'] = data['phenom']
                    if data['expiration'] != " ":
                        datapost['expiration'] = date_parse(data['issuance'])

                    if obj['feature'].get('geometry'):
                        poly = map(LinearRing, obj['feature']['geometry']['rings'])
                        datapost['warngeom'] = MultiPolygon(fromstr(str(Polygon(*poly).simplify(0.0003))),)
                        warninggeom = MultiPolygon(fromstr(str(Polygon(*poly))),)

                    datapost['issuance'] = date_parse(data['issuance'])
                    datapost['idp_subset'] = data['idp_subset']
                    datapost['warnid'] = data['warnid']

                    warningfeature = cls.objects.create(**datapost)
                    print 'Created Warning: {0}'.format(data.get('warnid'))

                warningfeature.save()

                #  Intersect with Departments and update table if overlap
                if(warninggeom != ''):

                    intersectDepartmentList = FireDepartment.objects.filter(geom__intersects=warninggeom)

                    if(intersectDepartmentList.count() > 0):

                        WeatherWarnings.add_warnings_to_departments(intersectDepartmentList, warningfeature)
                        print "Total intersecting Departments " + str(intersectDepartmentList.count())

            except KeyError:
                print '{0} failed.'.format(object)
                print url.format(object)

            except IntegrityError:
                print '{0} failed.'.format(object)
                print url.format(object)
                print sys.exc_info()

                try:
                    rollback()
                except:
                    pass

            except:
                print '{0} failed.'.format(object)
                print url.format(object)
                print sys.exc_info()

        print '{0} Total Weather Warnings.'.format(WeatherWarnings.objects.all().count())

    @classmethod
    def add_warnings_to_departments(self, departmentQuerySet, weatherWarnings):
        """
        adds and updates departement weather warnings
        """
        for fireDept in departmentQuerySet:

            try:

                print(weatherWarnings.prod_type + " for " + fireDept.name)
                print("Warning Expires " + str(weatherWarnings.expiration.strftime('%c')))

                #  Check if warning is already loaded and update as needed
                if DepartmentWarnings.objects.filter(warningname=weatherWarnings.warnid, departmentfdid=fireDept.id):

                    dataduplicate = DepartmentWarnings.objects.filter(warningname=weatherWarnings.warnid, departmentfdid=fireDept.id)
                    deptupdate = dataduplicate[0]
                    deptupdate.warningname = weatherWarnings.warnid
                    deptupdate.prod_type = weatherWarnings.prod_type
                    deptupdate.expiredate = weatherWarnings.expiration
                    deptupdate.issuedate = weatherWarnings.issuance
                    deptupdate.url = weatherWarnings.url
                    deptupdate.warngeom = weatherWarnings.warngeom

                    deptupdate.save()

                    print weatherWarnings.warnid + ' Department Warning Updated for ' + fireDept.name

                else:

                    dataadd = {}
                    dataadd['department'] = fireDept
                    dataadd['departmentfdid'] = fireDept.id
                    dataadd['departmentname'] = fireDept.name
                    dataadd['warningfdid'] = weatherWarnings
                    dataadd['warningname'] = weatherWarnings.warnid
                    dataadd['prod_type'] = weatherWarnings.prod_type
                    dataadd['expiredate'] = weatherWarnings.expiration
                    dataadd['issuedate'] = weatherWarnings.issuance
                    dataadd['url'] = weatherWarnings.url
                    dataadd['warngeom'] = weatherWarnings.warngeom

                    deptupdate = DepartmentWarnings.objects.create(**dataadd)
                    deptupdate.save()

                    print 'Department Warning Created'

            except:
                print 'Error running Department Query'
                return

    @property
    def warning_area(self):
        """
        Project data as needed
        """
        if self.district:
            try:
                return (self.warngeom.transform(102009, clone=True).area / 1000000) * 0.38610
            except:
                return

    @classmethod
    def requests_retry_session(self, retries=2, backoff_factor=0.3, status_forcelist=(500, 502, 504), session=None):
        session = session or requests.Session()
        retry = Retry(
            total=retries,
            read=retries,
            connect=retries,
            backoff_factor=backoff_factor,
            status_forcelist=status_forcelist,
        )
        adapter = HTTPAdapter(max_retries=retry)
        session.mount('http://', adapter)
        session.mount('https://', adapter)

        return session

    class Meta:
        verbose_name = 'Weather Warnings'
示例#21
0
class Job(UIDMixin, TimeStampedModelMixin):
    """
    Model for a Job.
    """

    # the "choices" setting for the django admin page drop down list requires a type that can be indexed
    visibility_choices = []
    for value in VisibilityState:
        visibility_choices.append((value.value, value.value))

    def __init__(self, *args, **kwargs):
        kwargs["the_geom"] = convert_polygon(kwargs.get("the_geom")) or ""
        kwargs["the_geom_webmercator"] = convert_polygon(
            kwargs.get("the_geom_webmercator")) or ""
        kwargs["the_geog"] = convert_polygon(kwargs.get("the_geog")) or ""
        super(Job, self).__init__(*args, **kwargs)

    user = models.ForeignKey(User,
                             on_delete=models.CASCADE,
                             null=True,
                             related_name="owner")
    name = models.CharField(max_length=100, db_index=True)
    description = models.CharField(max_length=1000, db_index=True)
    event = models.CharField(max_length=100,
                             db_index=True,
                             default="",
                             blank=True)
    region = models.ForeignKey(Region,
                               null=True,
                               blank=True,
                               on_delete=models.CASCADE)
    preset = models.ForeignKey(DatamodelPreset,
                               on_delete=models.CASCADE,
                               null=True,
                               blank=True)
    published = models.BooleanField(default=False,
                                    db_index=True)  # publish export
    visibility = models.CharField(max_length=10,
                                  choices=visibility_choices,
                                  default=VisibilityState.PRIVATE.value)
    featured = models.BooleanField(default=False,
                                   db_index=True)  # datapack is featured

    the_geom = models.MultiPolygonField(verbose_name="Extent for export",
                                        srid=4326,
                                        default="")
    the_geom_webmercator = models.MultiPolygonField(
        verbose_name="Mercator extent for export", srid=3857, default="")
    the_geog = models.MultiPolygonField(
        verbose_name="Geographic extent for export",
        geography=True,
        default="")
    original_selection = models.GeometryCollectionField(
        verbose_name="The original map selection",
        srid=4326,
        default=GeometryCollection,
        null=True,
        blank=True)

    include_zipfile = models.BooleanField(default=False)
    json_tags = models.JSONField(default=dict)
    last_export_run = models.ForeignKey("tasks.ExportRun",
                                        on_delete=models.DO_NOTHING,
                                        null=True,
                                        related_name="last_export_run")
    projections = models.ManyToManyField(Projection,
                                         related_name="projections")

    class Meta:  # pragma: no cover
        managed = True
        db_table = "jobs"

    def save(self, *args, **kwargs):
        self.the_geom = convert_polygon(self.the_geom)
        self.the_geog = GEOSGeometry(self.the_geom)
        self.the_geom_webmercator = self.the_geom.transform(ct=3857,
                                                            clone=True)
        super(Job, self).save(*args, **kwargs)

    def __str__(self):
        return "{0}".format(self.name)

    @property
    def overpass_extents(self):
        """
        Return the export extents in order required by Overpass API.
        """
        extents = GEOSGeometry(self.the_geom).extent  # (w,s,e,n)
        # overpass needs extents in order (s,w,n,e)
        overpass_extents = "{0},{1},{2},{3}".format(str(extents[1]),
                                                    str(extents[0]),
                                                    str(extents[3]),
                                                    str(extents[2]))
        return overpass_extents

    @property
    def extents(self):
        return GEOSGeometry(self.the_geom).extent  # (w,s,e,n)

    @property
    def filters(self):
        """
        Return key=value pairs for each tag in this export.

        Used in utils.overpass.filter to filter the export.
        """
        # Command-line key=value filters for osmfilter
        filters = []
        for tag in self.json_tags:
            kv = "{0}={1}".format(tag["key"], tag["value"])
            filters.append(kv)
        return filters

    @property
    def categorised_tags(self):
        """
        Return tags mapped according to their geometry types.
        """
        points = set()
        lines = set()
        polygons = set()
        for tag in self.json_tags:
            if "point" in tag["geom"]:
                points.add(tag["key"])
            if "line" in tag["geom"]:
                lines.add(tag["key"])
            if "polygon" in tag["geom"]:
                polygons.add(tag["key"])
        return {
            "points": sorted(list(points)),
            "lines": sorted(list(lines)),
            "polygons": sorted(list(polygons)),
        }

    @property
    def bounds_geojson(self):
        return serialize("geojson", [self],
                         geometry_field="the_geom",
                         fields=("name", "the_geom"))

    @property
    def attribute_classes(self):
        providers = [
            provider_task.provider
            for provider_task in self.data_provider_tasks.all()
        ]
        return AttributeClass.objects.filter(
            data_providers__in=providers).distinct()

    def get_last_run(self):
        return self.runs.last()
示例#22
0
class GeographicRegion(TranslatableModel, models.Model, ContentFetchingMixin):
    """Common model to represent levels 1, 2, 3"""
    __translatable__ = {
        "title": lambda l: models.CharField(
            _("Title in {LANGUAGE_NAME}".format(**l)),
            max_length=256,
            default='',
            blank=True,
        ),
    }

    level = models.IntegerField(
        choices=[
            (1, _('Country')),
            (2, _('Region')),
            (3, _('City')),
        ]
    )
    geom = models.MultiPolygonField(srid=4326,blank=True,
        null=True,)
    parent = models.ForeignKey('self', related_name='children', null=True, blank=True)
    name = models.CharField(max_length=256, default='')

    slug = models.CharField(max_length=100, default='')
    code = models.CharField(max_length=16, blank=True)

    hidden = models.BooleanField(default=False)

    languages_available = models.CharField(
        max_length=300,
        blank=True,
        help_text=_('Comma separated values of languages available in this region')
    )
    restrict_access_to = models.TextField(
        null=True,
        blank=True,
        help_text=_('Comma separated values of code of siblings visible from this region')
    )

    site = models.ForeignKey(Site, related_name='+', null=True, blank=True)
    
    objects = models.GeoManager()

    def __str__(self):
        return "%s %s" % (self.get_level_display(), self.name)

    @property
    def centroid(self):
        return self.geom.centroid 

    @property
    def depth(self):
        return len(list(self.parents))

    @property
    def parents(self):
        me = self
        while me.parent:
            me = me.parent

            yield me

    @property
    def important_information(self):
        pages = [{
                     "id": p.page.id,
                     "slug": p.page.slug,
                     "code": p.page.slug,
                     "title": p.page.title,
                     "name": p.page.title,
                     "hidden": False,
                     "metadata": {"page_title": p.page.title,},
                     "content": [{
                         "vector_icon": p.page.icon,
                         "hide_from_toc": p.page.pop_up,
                         "section": p.page.html(),
                         "metadata": {},
                         "title": p.page.title,
                         "important": False,
                         "anchor_name": p.page.slug,
                         "index": i,
                         "inherited": False,
                     }] + [{
                               "vector_icon": "",
                               "hide_from_toc": True,
                               "section": sp['html'],
                               "metadata": {
                                   "page_title": sp['title']
                               },
                               "title": sp['title'],
                               "important": False,
                               "anchor_name": sp['slug'],
                               "index": z,
                               "inherited": False,
                           } for z, sp in enumerate(p.page.get_sub_sections())
                           ]
                 } for i, p in enumerate(self.pages_with_order.filter(page__important=True).order_by('index'))]
        return pages

    @property
    def full_slug(self):
        return "--".join(reversed([self.slug] + [p.slug for p in self.parents]))

    @property
    def uri(self):
        return "/".join(reversed([self.slug] + [p.slug for p in self.parents if p.level != 2])) + '/'

    def get_all_languages(self):
        return set([])

    def get_sections(self, language='en', environment='production'):
        pages = [{
                     "vector_icon": p.page.icon,
                     "hide_from_toc": p.page.pop_up,
                     "section": p.page.html(language),
                     "metadata": {
                         "page_title": p.page.title
                     },
                     "title": p.page.title,
                     "important": False,
                     "anchor_name": p.page.slug,
                     "index": i,
                     "inherited": False,
                 } for i, p in enumerate(
            self.pages_with_order.filter(page__important=False, page__banner=False, page__status=environment).order_by(
                'index'))]

        page_like_objects = [
            [
                {
                    "vector_icon": "",
                    "hide_from_toc": True,
                    "section": sp['html'],
                    "metadata": {
                        "page_title": sp['title']
                    },
                    "title": sp['title'],
                    "important": False,
                    "anchor_name": sp['slug'],
                    "index": i,
                    "inherited": False,
                }
                for i, sp in enumerate(p.page.get_sub_sections(language))
                ]
            for p in self.pages_with_order.filter(page__important=False, page__banner=False, page__status=environment)
            ]
        return pages + list(itertools.chain.from_iterable(page_like_objects))

    def get_sub_pages(self, environment='production'):
        pages = [{
                     "id": p.page.id,
                     "slug": p.page.slug,
                     "code": p.page.slug,
                     "title": p.page.title,
                     "name": p.page.title,
                     "hidden": False,
                     "metadata": {"page_title": p.page.title,},
                     "content": [{
                         "vector_icon": p.page.icon,
                         "hide_from_toc": p.page.pop_up,
                         "section": p.page.html(),
                         "metadata": {},
                         "title": p.page.title,
                         "important": False,
                         "anchor_name": p.page.slug,
                         "index": i,
                         "inherited": False,
                     }] + [{
                               "vector_icon": "",
                               "hide_from_toc": True,
                               "section": sp['html'],
                               "metadata": {
                                   "page_title": sp['title']
                               },
                               "title": sp['title'],
                               "important": False,
                               "anchor_name": sp['slug'],
                               "index": z,
                               "inherited": False,
                           } for z, sp in enumerate(p.page.get_sub_sections())
                           ]
                 } for i, p in enumerate(
            self.pages_with_order.filter(page__important=True, page__banner=False, page__status=environment).order_by(
                'index'))]
        return pages

    def metadata(self, language='en', environment='production'):
        banners = self.pages_with_order.filter(page__banner=True, page__status=environment)
        return {
            "banners": [p.page.html() for p in banners],
            "page_title": self.title
        }

    def get_all_children(self):
        return GeographicRegion.objects.filter(Q(parent=self) | Q(parent__parent=self) | Q(id=self.id))

    class Meta:
        ordering = ['level', 'name']
示例#23
0
class Project(models.Model):
    TR55 = 'tr-55'
    GWLFE = 'gwlfe'
    MODEL_PACKAGES = (
        (TR55, 'Site Storm Model'),
        (GWLFE, 'Watershed Multi-Year Model'),
    )

    user = models.ForeignKey(User, on_delete=models.PROTECT)
    name = models.CharField(
        max_length=255)
    area_of_interest = models.MultiPolygonField(
        null=True,
        help_text='Base geometry for all scenarios of project')
    area_of_interest_name = models.CharField(
        null=True,
        max_length=255,
        help_text='A human name for the area of interest')
    is_private = models.BooleanField(
        default=True)
    model_package = models.CharField(
        choices=MODEL_PACKAGES,
        max_length=255,
        help_text='Which model pack was chosen for this project')
    created_at = models.DateTimeField(
        auto_now=False,
        auto_now_add=True)
    modified_at = models.DateTimeField(
        auto_now=True)
    is_activity = models.BooleanField(
        default=False,
        help_text='Projects with special properties')
    gis_data = models.TextField(
        null=True,
        help_text='Serialized JSON representation of additional'
                  ' data gathering steps, such as MapShed.')
    mapshed_job_uuid = models.ForeignKey(
        Job,
        to_field='uuid',
        related_name='mapshed_job',
        on_delete=models.SET_NULL,
        null=True,
        help_text='The job used to calculate the MapShed results.'
                  ' Used for getting the results of that job.')
    subbasin_mapshed_job_uuid = models.ForeignKey(
        Job,
        to_field='uuid',
        related_name='subbasin_mapshed_job',
        on_delete=models.SET_NULL,
        null=True,
        help_text='The job used to calculate the MapShed results'
                  ' for each HUC-12 sub-basin of the shape.')
    wkaoi = models.CharField(
        null=True,
        max_length=255,
        help_text='Well-Known Area of Interest ID for faster geoprocessing')
    layer_overrides = JSONField(
        default=dict,
        help_text='JSON object of layers to override defaults with')

    def __unicode__(self):
        return self.name

    @property
    def in_drb(self):
        return self.area_of_interest.within(settings.DRB_SIMPLE_PERIMETER)
示例#24
0
class Region(models.Model):
    name = models.CharField(max_length=50)
    the_geom = models.MultiPolygonField()
示例#25
0
class BaseMap(models.Model):
    name = models.CharField(max_length=50)
    geometry = models.MultiPolygonField(srid=4326)

    def __str__(self):
        return self.name
示例#26
0
class Parcel(models.Model):
    short_pin = models.CharField(max_length=100, blank=True, null=True)
    zoning = models.CharField(max_length=100, blank=True, null=True)
    pre_percent = models.DecimalField(max_digits=65535,
                                      decimal_places=65535,
                                      blank=True,
                                      null=True)
    pre_value = models.DecimalField(max_digits=65535,
                                    decimal_places=65535,
                                    blank=True,
                                    null=True)
    eq_value = models.DecimalField(max_digits=65535,
                                   decimal_places=65535,
                                   blank=True,
                                   null=True)
    tent_value = models.DecimalField(max_digits=65535,
                                     decimal_places=65535,
                                     blank=True,
                                     null=True)
    acreage_of_parent = models.DecimalField(max_digits=65535,
                                            decimal_places=65535,
                                            blank=True,
                                            null=True)
    assessed_value = models.DecimalField(max_digits=65535,
                                         decimal_places=65535,
                                         blank=True,
                                         null=True)
    building_assessment = models.DecimalField(max_digits=65535,
                                              decimal_places=65535,
                                              blank=True,
                                              null=True)
    capped_value = models.DecimalField(max_digits=65535,
                                       decimal_places=65535,
                                       blank=True,
                                       null=True)
    cvt_code = models.CharField(max_length=10, blank=True, null=True)
    cvt_description = models.CharField(max_length=40, blank=True, null=True)
    historical_district = models.CharField(max_length=4, blank=True, null=True)
    homestead_taxable = models.DecimalField(max_digits=65535,
                                            decimal_places=65535,
                                            blank=True,
                                            null=True)
    homestead_percent = models.DecimalField(max_digits=65535,
                                            decimal_places=65535,
                                            blank=True,
                                            null=True)
    lastupdate = models.DecimalField(max_digits=65535,
                                     decimal_places=65535,
                                     blank=True,
                                     null=True)
    legal_description = models.TextField(blank=True, null=True)
    owner_care_of = models.CharField(max_length=100, blank=True, null=True)
    owner_city = models.CharField(max_length=100, blank=True, null=True)
    owner_country = models.CharField(max_length=100, blank=True, null=True)
    owner_name = models.CharField(max_length=100, blank=True, null=True)
    owner_name2 = models.CharField(max_length=100, blank=True, null=True)
    owner_state = models.CharField(max_length=2, blank=True, null=True)
    owner_street = models.CharField(max_length=100, blank=True, null=True)
    owner_zip = models.CharField(max_length=20, blank=True, null=True)
    parent_parcel_num = models.CharField(max_length=40, blank=True, null=True)
    pin = models.CharField(max_length=40, blank=True, null=True)
    prop_city = models.CharField(max_length=100, blank=True, null=True)
    prop_class = models.CharField(max_length=10, blank=True, null=True)
    prop_class_description = models.CharField(max_length=100,
                                              blank=True,
                                              null=True)
    prop_state = models.CharField(max_length=2, blank=True, null=True)
    prop_street = models.CharField(max_length=100, blank=True, null=True)
    prop_street_num = models.DecimalField(max_digits=65535,
                                          decimal_places=65535,
                                          blank=True,
                                          null=True)
    prop_zip = models.CharField(max_length=20, blank=True, null=True)
    school_district = models.CharField(max_length=100, blank=True, null=True)
    school_name = models.CharField(max_length=100, blank=True, null=True)
    sev = models.DecimalField(max_digits=65535,
                              decimal_places=65535,
                              blank=True,
                              null=True)
    shape_area = models.DecimalField(max_digits=65535,
                                     decimal_places=65535,
                                     blank=True,
                                     null=True)
    shape_len = models.DecimalField(max_digits=65535,
                                    decimal_places=65535,
                                    blank=True,
                                    null=True)
    stated_area = models.CharField(max_length=20, blank=True, null=True)
    status_code = models.CharField(max_length=4, blank=True, null=True)
    status_desc = models.CharField(max_length=20, blank=True, null=True)
    taxable_value = models.DecimalField(max_digits=65535,
                                        decimal_places=65535,
                                        blank=True,
                                        null=True)
    txpyrs_care_of = models.CharField(max_length=100, blank=True, null=True)
    txpyrs_city = models.CharField(max_length=100, blank=True, null=True)
    txpyrs_country = models.CharField(max_length=100, blank=True, null=True)
    txpyrs_name = models.CharField(max_length=100, blank=True, null=True)
    txpyrs_state = models.CharField(max_length=100, blank=True, null=True)
    txpyrs_street_addr = models.CharField(max_length=100,
                                          blank=True,
                                          null=True)
    txpyrs_zip_code = models.CharField(max_length=20, blank=True, null=True)
    unit_apt_num = models.CharField(max_length=20, blank=True, null=True)
    geometry = models.TextField(blank=True, null=True)
    geom = models.MultiPolygonField(srid=4326, blank=True, null=True)
    centroid = models.PointField()
    lon_centroid = models.DecimalField(max_digits=65535,
                                       decimal_places=65535,
                                       blank=True,
                                       null=True)
    lat_centroid = models.DecimalField(max_digits=65535,
                                       decimal_places=65535,
                                       blank=True,
                                       null=True)
    county_gid = models.IntegerField(blank=True, null=True)
    cd_gid = models.IntegerField(blank=True, null=True)
    ct_gid = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'parcel'

    def __str__(self):
        return '%s' % self.pin
示例#27
0
class Park(models.Model):
    """
    Park or similar Open Space.
    """

    ACCESS_CHOICES = (
        ('y', 'Yes'),
        ('n', 'No'),
        ('u', 'Unknown'),
    )

    os_id = models.CharField('OS ID',
                             max_length=9,
                             null=True,
                             blank=True,
                             help_text='Refers to MassGIS OS_ID')
    name = models.CharField(max_length=100, blank=True, null=True)
    slug = models.SlugField(max_length=100, blank=True, null=True, unique=True)
    alt_name = models.CharField('Alternative name',
                                max_length=100,
                                blank=True,
                                null=True)
    description = models.TextField(blank=True, null=True)
    address = models.CharField(max_length=50, blank=True, null=True)
    phone = models.CharField(max_length=50, blank=True, null=True)
    neighborhoods = models.ManyToManyField(Neighborhood,
                                           related_name='neighborhoods',
                                           blank=True)
    parktype = models.ForeignKey(Parktype, blank=True, null=True)
    parkowner = models.ForeignKey(Parkowner, blank=True, null=True)
    friendsgroup = models.ForeignKey("Friendsgroup", blank=True, null=True)
    events = models.ManyToManyField("Event",
                                    related_name="events",
                                    blank=True,
                                    null=True)
    access = models.CharField(max_length=1,
                              blank=True,
                              null=True,
                              choices=ACCESS_CHOICES)
    area = models.FloatField(blank=True, null=True)
    image = models.ImageField(blank=True, upload_to="parkimages")

    def parkimage_thumb(self):
        if self.image:
            thumb = get_thumbnail(self.image.file,
                                  settings.ADMIN_THUMBS_SIZE,
                                  crop='center',
                                  quality=80)
            return u'<img width="%s" height="%s" src="%s" />' % (
                thumb.width, thumb.height, thumb.url)
        else:
            return None

    geometry = models.MultiPolygonField(srid=26986)
    objects = models.GeoManager()

    class Meta:
        verbose_name = _('Park')
        verbose_name_plural = _('Parks')
        ordering = ['name']

    def __unicode__(self):
        return self.name

    @models.permalink
    def get_absolute_url(self):
        return ('park', [slugify(self.name)])

    def area_acres(self):
        return self.area / 4047

    def lat_long(self):
        self.geometry.transform(4326)
        return [self.geometry.centroid.y, self.geometry.centroid.x]

    def save(self, *args, **kwargs):

        self.area = self.geometry.area
        self.slug = slugify(self.name)

        super(Park, self).save(*args, **kwargs)

        try:
            # cache containing neighorhood
            # doesn't work with admin forms, m2m get cleared during admin save
            neighborhoods = Neighborhood.objects.filter(
                geometry__intersects=self.geometry)
            self.neighborhoods.clear()
            self.neighborhoods.add(*neighborhoods)
        except TypeError:
            self.neighborhoods = None
示例#28
0
class JburgLanduse(models.Model):
    cartotypen = models.CharField(null=True, blank=True, max_length=255)
    geom = models.MultiPolygonField(srid=4326)

    def __str__(self):
        return self.cartotypen
示例#29
0
class Project(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             verbose_name=_('user'),
                             related_name='projects',
                             null=True,
                             blank=True,
                             on_delete=models.PROTECT)
    created_at = models.DateTimeField(verbose_name=_('created at'),
                                      auto_now_add=True,
                                      editable=False)
    modified_at = models.DateTimeField(verbose_name=_('modified at'),
                                       auto_now=True,
                                       editable=False)
    name = models.CharField(max_length=255, verbose_name=_('name'))
    identifier = models.CharField(max_length=50,
                                  verbose_name=_('identifier'),
                                  db_index=True,
                                  blank=True,
                                  null=True)
    type = models.ForeignKey(ProjectType,
                             verbose_name=_('type'),
                             related_name='projects',
                             on_delete=models.PROTECT)
    attribute_data = JSONField(verbose_name=_('attribute data'),
                               default=dict,
                               blank=True,
                               null=True,
                               encoder=DjangoJSONEncoder)
    phase = models.ForeignKey('ProjectPhase',
                              verbose_name=_('phase'),
                              null=True,
                              related_name='projects',
                              on_delete=models.PROTECT)

    geometry = models.MultiPolygonField(null=True, blank=True)

    class Meta:
        verbose_name = _('project')
        verbose_name_plural = _('projects')
        ordering = ('name', )

    def __str__(self):
        return self.name

    def get_attribute_data(self):
        ret = {}

        for attribute in Attribute.objects.all().prefetch_related(
                'value_choices'):
            deserialized_value = None

            if attribute.value_type == Attribute.TYPE_GEOMETRY:
                deserialized_value = self.geometry
            elif attribute.value_type == Attribute.TYPE_IMAGE:
                try:
                    deserialized_value = ProjectAttributeImage.objects.get(
                        attribute=attribute,
                        project=self,
                    ).image
                except ProjectAttributeImage.DoesNotExist:
                    deserialized_value = None
            elif attribute.identifier in self.attribute_data:
                deserialized_value = attribute.deserialize_value(
                    self.attribute_data[attribute.identifier])

            ret[attribute.identifier] = deserialized_value
        return ret

    def set_attribute_data(self, data):
        self.attribute_data = {}
        self.geometry = None
        self.update_attribute_data(data)

    def update_attribute_data(self, data):
        attributes = {
            a.identifier: a
            for a in Attribute.objects.all().prefetch_related('value_choices')
        }

        for identifier, value in data.items():
            attribute = attributes.get(identifier)

            if not attribute:
                continue

            if attribute.value_type == Attribute.TYPE_GEOMETRY:
                self.geometry = value
            elif attribute.value_type == Attribute.TYPE_IMAGE:
                if value is False:
                    ProjectAttributeImage.objects.filter(
                        attribute=attribute, project=self).delete()
                elif value is None:
                    # None is handled in the same way as omitting this attribute from the update in the first place
                    # would have been, ie. do nothing. This is to make life easier as the form where these images
                    # mainly come from uses False for "delete" and None for "no update".
                    continue
                else:
                    ProjectAttributeImage.objects.update_or_create(
                        attribute=attribute,
                        project=self,
                        defaults={'image': value})
            else:
                serialized_value = attribute.serialize_value(value)

                if serialized_value is not None:
                    self.attribute_data[identifier] = serialized_value
                else:
                    self.attribute_data.pop(identifier, None)

    def get_time_line(self):
        timeline = [{
            'content': 'Luontipvm',
            'start': self.created_at,
            'group': self.id,
            'type': 'point',
        }]

        for log_entry in self.phase_logs.order_by('created_at'):
            timeline.append({
                # 'title': None,
                'content': log_entry.phase.name,
                'start': log_entry.created_at,
                'end': None,
                'group': self.id,
                'type': 'background',
                'className': log_entry.phase.color,
            })

            if timeline[-2]['type'] == 'background':
                timeline[-2]['end'] = log_entry.created_at

        if timeline[-1]['type'] == 'background' and not timeline[-1]['end']:
            timeline[-1]['end'] = timezone.now()

        for attribute in Attribute.objects.filter(
                value_type=Attribute.TYPE_DATE):
            if attribute.identifier in self.attribute_data and self.attribute_data[
                    attribute.identifier]:
                start_dt = attribute.deserialize_value(
                    self.attribute_data[attribute.identifier])

                timeline.append({
                    'type': 'point',
                    'content': attribute.name,
                    'start': start_dt,
                    'group': self.id,
                })

                # TODO: Remove hard-coded logic
                if attribute.identifier == 'oas_aineiston_esillaoloaika_alkaa':
                    timeline.append({
                        'type':
                        'point',
                        'content':
                        'OAS-paketin määräaika',
                        'start':
                        start_dt - datetime.timedelta(weeks=2),
                        'group':
                        self.id,
                    })

                if attribute.identifier == 'ehdotuksen_suunniteltu_lautakuntapaivamaara_arvio' and \
                        'prosessin_kokoluokka' in self.attribute_data:
                    weeks = 6 if self.attribute_data[
                        'prosessin_kokoluokka'] in ['l', 'xl'] else 14

                    timeline.append({
                        'type':
                        'point',
                        'content':
                        'Lautakuntapaketin määräaika',
                        'start':
                        start_dt - datetime.timedelta(weeks=weeks),
                        'group':
                        self.id,
                    })

        return timeline
示例#30
0
class AOI(GeoQBase, Assignment):
    """
    Low-level organizational object. Now (6/1/14) referred to as a 'Workcell'
    """

    STATUS_VALUES = STATUS_VALUES_LIST
    STATUS_CHOICES = [(choice, choice) for choice in STATUS_VALUES]

    PRIORITIES = [(n, n) for n in range(1, 6)]

    analyst = models.ForeignKey(
        User,
        blank=True,
        null=True,
        help_text="User assigned to work the workcell.")
    job = models.ForeignKey(Job, related_name="aois")
    reviewers = models.ManyToManyField(
        User,
        blank=True,
        null=True,
        related_name="aoi_reviewers",
        help_text='Users that actually reviewed this work.')
    objects = AOIManager()
    polygon = models.MultiPolygonField()
    priority = models.SmallIntegerField(choices=PRIORITIES,
                                        max_length=1,
                                        default=5)
    status = models.CharField(max_length=15,
                              choices=STATUS_CHOICES,
                              default='Unassigned')

    class Meta:
        permissions = (
            ('assign_workcells', 'Assign Workcells'),
            ('certify_workcells', 'Certify Workcells'),
        )

    def __unicode__(self):
        aoi_obj = '%s - AOI %s' % (self.name, self.id)
        return aoi_obj

    @property
    def log(self):
        return Comment.objects.filter(aoi=self).order_by('created_at')

    @property
    def assignee_name(self):
        if self.assignee_id is None:
            return 'Unknown'
        else:
            if self.assignee_type_id == AssigneeType.USER:
                return User.objects.get(id=self.assignee_id).username
            else:
                return Group.objects.get(id=self.assignee_id).name

    #def save(self):
    # if analyst or reviewer updated, then create policy to give them permission to edit this object.....
    # -- Afterwards -- check how this will work with the views.

    def get_absolute_url(self):
        if self.job.editable_layer_id is None:
            return reverse('aoi-work', args=[self.id])
        else:
            return reverse('aoi-mapedit', args=[self.id])

    def geoJSON(self):
        """
        Returns geoJSON of the feature.
        """

        if self.id is None:
            self.id = 1

        geojson = SortedDict()
        geojson["type"] = "Feature"
        geojson["properties"] = dict(
            id=self.id,
            status=self.status,
            analyst=(self.analyst.username
                     if self.analyst is not None else 'None'),
            assignee=self.assignee_name,
            priority=self.priority,
            delete_url=reverse('aoi-deleter', args=[self.id]))
        geojson["geometry"] = json.loads(self.polygon.json)

        geojson["properties"]["absolute_url"] = self.get_absolute_url()

        return clean_dumps(geojson)

    def logJSON(self):
        return [ob.to_dict() for ob in self.log]

    def properties_json(self):
        """
        Returns json of the feature properties.
        """

        if self.id is None:
            self.id = 1

        properties_main = self.properties or {}
        properties_built = dict(status=self.status,
                                analyst=(self.analyst.username if self.analyst
                                         is not None else 'Unassigned'),
                                priority=self.priority)
        prop_json = dict(properties_built.items() + properties_main.items())

        return clean_dumps(prop_json)

    def map_detail(self):
        """
        Get map coordinates for MapEdit
        """
        center = self.polygon.centroid
        return "15/%f/%f" % (center.y, center.x)

    def grid_geoJSON(self):
        """
        Return geoJSON of workcells for export
        """

        if self.id is None:
            self.id = 1

        geojson = SortedDict()
        geojson["type"] = "Feature"
        geojson["properties"] = dict(id=self.id,
                                     priority=self.priority,
                                     status=self.status)
        geojson["geometry"] = json.loads(self.polygon.json)

        return clean_dumps(geojson)

    def user_can_complete(self, user):
        """
        Returns whether the user can update the AOI as complete.
        """
        return user == self.analyst or user in self.job.reviewers.all()

    class Meta:
        verbose_name = 'Area of Interest'
        verbose_name_plural = 'Areas of Interest'