Пример #1
0
class Feature(models.Model):
    """
    Model to represent features created in the application.
    """

    STATUS_VALUES = [
        'Unassigned', 'In work', 'Awaiting review', 'In review', 'Completed'
    ]  #'Assigned'
    STATUS_CHOICES = [(choice, choice) for choice in STATUS_VALUES]

    aoi = models.ForeignKey(AOI, related_name='features', editable=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    objects = models.GeoManager()
    analyst = models.ForeignKey(User, editable=False)
    template = models.ForeignKey("FeatureType", on_delete=models.PROTECT)
    status = models.CharField(max_length=15,
                              choices=STATUS_CHOICES,
                              default='In work')

    # Allow the user to save their own properties
    properties = JSONField(load_kwargs={}, blank=True, null=True)

    # These help the user identify features when data is exposed outside of the application (Geoserver).
    job = models.ForeignKey(Job, editable=False)
    project = models.ForeignKey(Project, editable=False)

    #Try this vs having individual models
    the_geom = models.GeometryField(blank=True, null=True)

    def geoJSON(self, as_json=True, using_style_template=True):
        """
        Returns geoJSON of the feature.
        Try to conform to https://github.com/mapbox/simplestyle-spec/tree/master/1.0.0
        """
        properties_main = self.properties or {}
        properties_built = dict(
            id=self.id,
            status=self.status,
            analyst=self.analyst.username,
            created_at=datetime.strftime(self.created_at,
                                         '%Y-%m-%dT%H:%M:%S%Z'),
            updated_at=datetime.strftime(self.updated_at,
                                         '%Y-%m-%dT%H:%M:%S%Z'),
        )
        properties_template = self.template.properties or {}

        # properties_template can return a list from it's backing model, make sure we get the Dict
        if type(properties_template) == types.ListType:
            properties_template = properties_template[0]

        # srj: if using_style_template set, we're styling object from its feature id, else we'll
        #      just use the style properties (which should already be included if defined for feature)
        #      (we may want to set some defaults later on to make sure)
        if using_style_template:
            properties_built['template'] = self.template.id if hasattr(
                self.template, "id") else None

        properties = dict(properties_built.items() + properties_main.items() +
                          properties_template.items())

        feature_type = FeatureType.objects.get(id=self.template.id)

        geojson = SortedDict()
        geojson["type"] = "Feature"
        geojson["properties"] = properties
        geojson["geometry"] = json.loads(self.the_geom.json)

        if feature_type and using_style_template:
            geojson["style"] = feature_type.style_to_geojson()
        else:
            geojson["style"] = feature_type.style

        if (as_json):
            return clean_dumps(geojson)
        else:
            for key in properties:
                if isinstance(properties[key], str) or isinstance(
                        properties[key], unicode):
                    properties[key] = properties[key].replace(
                        '<', '&ltl').replace('>', '&gt;').replace(
                            "javascript:", "j_script-")
            return geojson

    def json_item(self, show_detailed_properties=False):
        properties_main = self.properties or {}

        #Pull the County data if it exists, otherwise find it and add it back to the object
        if properties_main.has_key('county'):
            county = properties_main['county']
        else:
            county_list = Counties.objects.filter(
                poly__contains=self.the_geom.centroid.wkt)
            if len(county_list):
                county = str(county_list[0].name)
            else:
                county = "Unknown"
            self.properties = properties_main

        if not show_detailed_properties:
            if 'linked_items' in properties_main:
                properties_main['linked_items'] = True
            else:
                properties_main['linked_items'] = False

        properties_built = dict(
            id=self.id,
            feature_type=str(self.template.name) if hasattr(
                self.template, "name") else self.template.id,
            analyst=str(self.analyst.username),
            workcell_id=self.aoi.id,
            status=str(self.status),
            county=county
            # created_at=datetime.strftime(self.created_at, '%Y-%m-%dT%H:%M:%S%Z'),
            # updated_at=datetime.strftime(self.updated_at, '%Y-%m-%dT%H:%M:%S%Z'),
        )

        properties_feature = dict(self.template.properties or {})

        properties = dict(properties_main.items() + properties_built.items() +
                          properties_feature.items())
        return properties

    def __unicode__(self):
        return "Feature created for {0}".format(self.aoi.name)

    def clean(self):
        obj_geom_type = self.the_geom.geom_type.lower()
        template_geom_type = self.template.type.lower()
        if obj_geom_type != template_geom_type:
            error_text = "Feature type {0} does not match the template's feature type {1}."
            raise ValidationError(
                error_text.format(obj_geom_type, template_geom_type))

    class Meta:
        ordering = (
            '-updated_at',
            'aoi',
        )
Пример #2
0
class AggregationBase(models.Model):
    slug = models.CharField(max_length=50, primary_key=True)
    centroid = models.GeometryField(blank=True, null=True)

    sum_schools = models.BigIntegerField(null=True, blank=True)
    sum_govt_schools = models.BigIntegerField(null=True, blank=True)
    sum_rural_schools = models.BigIntegerField(null=True, blank=True)
    avg_distance_brc = models.FloatField(null=True, blank=True)
    avg_distance_crc = models.FloatField(null=True, blank=True)
    sum_pre_primary_schools = models.BigIntegerField(null=True, blank=True)
    sum_residential_schools = models.BigIntegerField(null=True, blank=True)
    sum_pre_primary_students = models.BigIntegerField(null=True, blank=True)
    avg_pre_primary_students = models.FloatField(null=True, blank=True)
    sum_shift_schools = models.BigIntegerField(null=True, blank=True)
    sum_no_of_working_days = models.BigIntegerField(null=True, blank=True)
    avg_no_of_working_days = models.FloatField(null=True, blank=True)
    sum_no_of_acad_inspection = models.BigIntegerField(null=True, blank=True)
    avg_no_of_acad_inspection = models.FloatField(null=True, blank=True)
    sum_visits_by_brc = models.BigIntegerField(null=True, blank=True)
    avg_visits_by_brc = models.FloatField(null=True, blank=True)
    sum_visits_by_crc = models.BigIntegerField(null=True, blank=True)
    avg_visits_by_crc = models.FloatField(null=True, blank=True)
    sum_school_dev_grant_recd = models.FloatField(null=True, blank=True)
    avg_school_dev_grant_recd = models.FloatField(null=True, blank=True)
    sum_school_dev_grant_expnd = models.FloatField(null=True, blank=True)
    avg_school_dev_grant_expnd = models.FloatField(null=True, blank=True)
    sum_tlm_grant_recd = models.FloatField(null=True, blank=True)
    avg_tlm_grant_recd = models.FloatField(null=True, blank=True)
    sum_tlm_grant_expnd = models.FloatField(null=True, blank=True)
    avg_tlm_grant_expnd = models.FloatField(null=True, blank=True)
    sum_funds_from_students_recd = models.FloatField(null=True, blank=True)
    avg_funds_from_students_recd = models.FloatField(null=True, blank=True)
    sum_funds_from_students_expnd = models.FloatField(null=True, blank=True)
    avg_funds_from_students_expnd = models.FloatField(null=True, blank=True)
    sum_tot_clrooms = models.BigIntegerField(null=True, blank=True)
    avg_tot_clrooms = models.FloatField(null=True, blank=True)
    sum_classrooms_in_good_condition = models.BigIntegerField(null=True, blank=True)
    avg_classrooms_in_good_condition = models.FloatField(null=True, blank=True)
    sum_has_classrooms_in_good_condition = models.BigIntegerField(null=True, blank=True)
    sum_classrooms_require_major_repair = models.BigIntegerField(null=True, blank=True)
    avg_classrooms_require_major_repair = models.FloatField(null=True, blank=True)
    sum_classrooms_require_minor_repair = models.BigIntegerField(null=True, blank=True)
    avg_classrooms_require_minor_repair = models.FloatField(null=True, blank=True)
    sum_other_rooms_in_good_cond = models.BigIntegerField(null=True, blank=True)
    avg_other_rooms_in_good_cond = models.FloatField(null=True, blank=True)
    sum_other_rooms_need_major_rep = models.BigIntegerField(null=True, blank=True)
    avg_other_rooms_need_major_rep = models.FloatField(null=True, blank=True)
    sum_other_rooms_need_minor_rep = models.BigIntegerField(null=True, blank=True)
    avg_other_rooms_need_minor_rep = models.FloatField(null=True, blank=True)
    sum_toilet_common = models.BigIntegerField(null=True, blank=True)
    avg_toilet_common = models.FloatField(null=True, blank=True)
    sum_toilet_boys = models.BigIntegerField(null=True, blank=True)
    avg_toilet_boys = models.FloatField(null=True, blank=True)
    sum_toilet_girls = models.BigIntegerField(null=True, blank=True)
    avg_toilet_girls = models.FloatField(null=True, blank=True)
    sum_kitchen_devices_grant = models.BigIntegerField(null=True, blank=True)
    avg_kitchen_devices_grant = models.FloatField(null=True, blank=True)
    sum_has_mdm = models.BigIntegerField(null=True, blank=True)
    sum_has_cal_lab = models.BigIntegerField(null=True, blank=True)
    sum_has_separate_room_for_headmaster = models.BigIntegerField(null=True, blank=True)
    sum_has_electricity = models.BigIntegerField(null=True, blank=True)
    sum_has_boundary_wall = models.BigIntegerField(null=True, blank=True)
    sum_has_library = models.BigIntegerField(null=True, blank=True)
    sum_books_in_library = models.BigIntegerField(null=True, blank=True)
    avg_books_in_library = models.FloatField(null=True, blank=True)
    sum_has_playground = models.BigIntegerField(null=True, blank=True)
    sum_has_blackboard = models.BigIntegerField(null=True, blank=True)
    sum_has_drinking_water = models.BigIntegerField(null=True, blank=True)
    sum_has_medical_checkup = models.BigIntegerField(null=True, blank=True)
    sum_has_ramps = models.BigIntegerField(null=True, blank=True)
    sum_has_computer = models.BigIntegerField(null=True, blank=True)
    sum_has_toilet = models.BigIntegerField(null=True, blank=True)
    sum_has_girls_toilet = models.BigIntegerField(null=True, blank=True)
    sum_no_of_computers = models.BigIntegerField(null=True, blank=True)
    avg_no_of_computers = models.FloatField(null=True, blank=True)
    sum_male_tch = models.BigIntegerField(null=True, blank=True)
    avg_male_tch = models.FloatField(null=True, blank=True)
    sum_female_tch = models.BigIntegerField(null=True, blank=True)
    avg_female_tch = models.FloatField(null=True, blank=True)
    sum_noresp_tch = models.BigIntegerField(null=True, blank=True)
    avg_noresp_tch = models.FloatField(null=True, blank=True)
    sum_head_teacher = models.BigIntegerField(null=True, blank=True)
    avg_head_teacher = models.FloatField(null=True, blank=True)
    sum_graduate_teachers = models.BigIntegerField(null=True, blank=True)
    avg_graduate_teachers = models.FloatField(null=True, blank=True)
    sum_tch_with_professional_qualification = models.BigIntegerField(null=True, blank=True)
    avg_tch_with_professional_qualification = models.FloatField(null=True, blank=True)
    sum_days_involved_in_non_tch_assgn = models.BigIntegerField(null=True, blank=True)
    avg_days_involved_in_non_tch_assgn = models.FloatField(null=True, blank=True)
    sum_teachers_involved_in_non_tch_assgn = models.BigIntegerField(null=True, blank=True)
    avg_teachers_involved_in_non_tch_assgn = models.FloatField(null=True, blank=True)
    sum_boys = models.BigIntegerField(blank=True, null=True)
    avg_boys = models.FloatField(blank=True, null=True)
    sum_girls = models.BigIntegerField(blank=True, null=True)
    avg_girls = models.FloatField(blank=True, null=True)

    objects = models.GeoManager()

    class Meta:
        abstract = True

    @property
    def session(self):
        """Finds session of the current object from table name
        """
        # extracts the 4 digit session from table name
        session = filter(str.isdigit, str(self._meta.db_table))
        listified_session = list(session)
        listified_session.insert(2, '-')
        session = ''.join(listified_session)
        return session
Пример #3
0
class Station(models.Model):
    id = models.IntegerField(primary_key=True)
    data_id = models.IntegerField(db_index=True)
    code = models.CharField(max_length=16, db_index=True)
    name = models.CharField(max_length=255)
    zone = models.CharField(max_length=16)
    state = models.CharField(max_length=128)
    address = models.CharField(max_length=512, blank=True)
    point = models.PointField(blank=True, null=True)
    objects = models.GeoManager()

    def __unicode__(self):
        return "%s: %s" % (
            self.code,
            self.name,
        )

    @classmethod
    def import_from_csv(kls, path_to_csv):
        stations = csv.DictReader(open(path_to_csv))
        for s in stations:
            station = Station(**s)
            station.save()
            print station.id

    @classmethod
    def import_locations(kls, path_to_json):
        geojson = json.load(open(path_to_json))
        features = geojson['features']
        for f in features:
            station_code = f['properties']['code'].upper()
            station = Station.objects.get(code=station_code)
            lon = f['geometry']['coordinates'][0]
            lat = f['geometry']['coordinates'][1]
            if lon == 0 or lon == '':
                continue
            try:
                pt = Point(lon, lat)
            except:
                print json.dumps(f)
                raise Error('bad lat-long')
            station.point = pt
            station.save()
            print station_code

    def get_geojson(self):
        return {
            'type': 'Feature',
            'geometry': json.loads(self.point.geojson) if self.point else None,
            'properties': {
                'code': self.code,
                'name': self.name,
                'state': self.state,
                'address': self.address
            }
        }

    def get_destinations(self):
        geojson = self.get_geojson()
        geojson['properties']['destinations'] = []
        for s in self.schedule_set.filter(
                minor_stop_number=0).select_related('train__to_station'):
            last_stop = s.train.to_station
            last_stop_geojson = last_stop.get_geojson()
            last_stop_geojson['properties']['train_number'] = s.train.number
            last_stop_geojson['properties']['train_name'] = s.train.name
            geojson['properties']['destinations'].append(last_stop_geojson)
        return geojson

    @classmethod
    def get_all_destinations(kls):
        return [s.get_destinations() for s in Station.objects.all()]

    @classmethod
    def import_osm_geojson(kls, path_to_file):
        osm_data = json.load(open(path_to_file))
        count = 0
        for feature in osm_data['features']:
            if 'ref' in feature['properties']:
                count += 1
                code = feature['properties']['ref']
                try:
                    station = Station.objects.get(code=code)
                except:
                    continue
                station.point = Point(feature['geometry']['coordinates'][0],
                                      feature['geometry']['coordinates'][1])
                station.save()
                print station.name
        print count

    @classmethod
    def match_osm_names(kls, path_to_file):
        osm_data = json.load(open(path_to_file))
        for feature in osm_data['features']:
            if 'name' in feature['properties']:
                name = feature['properties']['name']
                first_name = name.split(' ')[0]
                stations = Station.objects.filter(point=None).filter(
                    name__iexact=first_name)
                if stations.count() == 1:
                    station = stations[0]
                    station.point = Point(
                        feature['geometry']['coordinates'][0],
                        feature['geometry']['coordinates'][1])
                    station.save()
                    print station.name
Пример #4
0
class Boundary(MyModel):
    poly = models.PolygonField("Boundary", blank=True)
    isconfirmed = models.BooleanField("Confirmed?", )
    boundary_type = models.ForeignKey(BoundaryType)

    owner = CurrentUserField(blank=True, related_name="nam_owner", default=1)
    modifier = CurrentUserField(blank=True,
                                related_name="nam_modifier",
                                default=1)

    related = models.ManyToManyField("self",
                                     symmetrical=False,
                                     null=True,
                                     blank=True,
                                     through='boundaries.BoundariesRelated',
                                     related_name='related_boundary')

    name = models.CharField("Name", max_length=128, blank=True)

    number = models.PositiveIntegerField("Number", null=True, blank=True)
    geo_name_id = models.PositiveIntegerField("GEO Name ID",
                                              null=True,
                                              blank=True)

    previousnumber = models.CharField("Previous Number",
                                      max_length=32,
                                      blank=True)

    code = models.CharField("Code", max_length=32, blank=True)
    previouscode = models.CharField("Previous Code", max_length=32, blank=True)

    postalcode = models.CharField("Zip Code", max_length=32, blank=True)

    #area_kml = models.DecimalField("Area Kilometers", max_digits=11, decimal_places=7, null=True, blank=True)
    #population = models.PositiveIntegerField("Population", null=True, blank=True)

    #population_target_language = models.PositiveIntegerField("English Population", null=True, blank=True)
    notes = models.TextField("Notes", blank=True)

    objects = models.GeoManager()

    #helper functions
    #b = Boundary.objects.all()[0]
    #pt = b.pt_from_long_lat(-84.1453933304581, 9.97895563839969)
    #b.contains(pt)

    def pt_from_long_lat(self, long, lat):
        from django.contrib.gis.geos import fromstr
        return fromstr("POINT(%s %s)" % (long, lat))

    def contains(self, pt):
        return self.poly.contains(pt)

    # http://nemo.seaports2100.org/doku.php/tutorials/sebastian/geomysql
    # input - KML Polygon (well-formatted)
    def kml2poly(self, kml_str):
        # Begin MySQL Polygon output
        output = 'POLYGON('

        # Import XML parser
        from xml.dom.minidom import parseString

        # Parse KML kml_str
        i = parseString(kml_str)

        # Get outer rings coordinates
        outercoords = i.getElementsByTagName(
            "outerBoundaryIs")[0].getElementsByTagName(
                "coordinates")[0].firstChild.nodeValue.strip()

        # Start outer ring output
        output += '('

        # For each point in coordinates, add to output
        for pt in outercoords.split(' '):
            lon, lat, elev = pt.split(',')
            output += lon + " " + lat + ","

        # Strip last comma from output and close outer ring
        output = output[:-1] + ")"

        # Get number of inner rings
        irings = len(i.getElementsByTagName("innerBoundaryIs"))

        # For each inner ring, add to output
        for n in range(irings):
            # Get rind coordinates
            innercoords = i.getElementsByTagName(
                "innerBoundaryIs")[n].getElementsByTagName(
                    "coordinates")[0].firstChild.nodeValue.strip()

            # Start output
            output += ",("

            # For each point in coordinates, add to output
            for pt in outercoords.split(' '):
                lon, lat, elev = pt.split(',')
                output += lon + " " + lat + ","

            # Strip last comma from output and close ring
            output = output[:-1] + ")"

        # End Polygon output
        output += ')'

        # Return formatted MySQL Polygon
        return output

    #Load poly from kml string:
    #'<Polygon><outerBoundaryIs><LinearRing><coordinates>-84.1453933305,9.9789556384,0 -84.1436421837,9.97173599811,0 -84.1367912059,9.96863308888,0 -84.1352551122,9.97121372626,0 -84.135777384,9.97176671998,0 -84.1358081059,9.97228899183,0 -84.1338111841,9.97342570116,0 -84.1351015028,9.97708160411,0 -84.1324901436,9.98294948196,0 -84.1326437529,9.98301092571,0 -84.134087681,9.98172060702,0 -84.1369448152,9.98150555391,0 -84.1379586371,9.98110616955,0 -84.138450187,9.98273442885,0 -84.1406007182,9.98341031007,0 -84.1416759838,9.98193566014,0 -84.1453933305,9.9789556384,0</coordinates></LinearRing></outerBoundaryIs></Polygon>'
    def set_poly_from_kml_str(self, kml_str):
        self.poly = self.kml2poly(kml_str)

    # a start for creating links to where this boundary may reside/be contained within
    def geo_tag(self):
        center_pt = self.center_pt
        bscontains = Boundary.objects.exclude(boundary_type__id=5).filter(
            poly__contains=center_pt)
        for b in bscontains:
            print b

    @property
    def coords(self):
        return self.poly.coords if self.poly else None

    @property
    def boundary(self):
        return self.poly.boundary if self.poly else None

    @property
    def kml(self):
        return self.poly.kml if self.poly else None

    @property
    def center_pt(self):
        return self.poly.centroid if self.poly else None

    @property
    def full_name(self):
        ret = u''
        if self.boundary_type:
            ret = self.boundary_type.title
        ret += u'-' if ret else u''
        if self.name:
            ret += self.name

        return ret

    @property
    def number_path(self):
        related_title = u''
        related_title = str(self.number) if self.number else u''
        return related_title

    class Meta:
        #app_label = u'boundaries'
        db_table = u'flt_boundaries'
        # db_table = u'flt_boundaries_test'
        #unique_together = ("boundary_type", "name", "number", "code"),
        verbose_name_plural = "boundaries"
        permissions = (('access_boundaries', 'Access to Boundaries'), )

    #def get_absolute_url(self):
    #return "/boundary/%i/" % self.id

    def type(self):
        return u'boundary'

    def __unicode__(self):
        return self.full_name + ' | ' + self.number_path + ' : ' + str(self.id)
Пример #5
0
class Job(UIDMixin, 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)

    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, blank=True, on_delete=models.SET_NULL)
    provider_tasks = models.ManyToManyField(DataProviderTask, related_name='provider_tasks')
    preset = models.ForeignKey(DatamodelPreset, null=True, blank=True)
    published = models.BooleanField(default=False, db_index=True)  # publish export
    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)
    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'))
Пример #6
0
class Lieu(models.Model):
    name = models.CharField(max_length=512,
                            help_text=_("nom du lieu"),
                            verbose_name=_("lieu de la représentation"))
    # allowed_users = models.ManyToManyField(CustomUser,
    # null = True,
    # blank = True,
    # verbose_name = _('utilisateur authorisé'))
    phoneNumber = models.CharField(
        max_length=512,
        null=True,
        blank=True,
        verbose_name=_("numéro de téléphone du lieu"))
    city = models.CharField(max_length=512, verbose_name=_("ville"))
    zipCode = models.CharField(max_length=64,
                               null=True,
                               blank=True,
                               verbose_name=_("code postal"))
    adress = models.CharField(max_length=512, verbose_name=_("adresse"))
    adress2 = models.CharField(max_length=512,
                               null=True,
                               blank=True,
                               verbose_name=_("suite de l'adresse"))
    website = models.URLField(null=True,
                              blank=True,
                              verbose_name=_("site web"))
    region = models.ForeignKey(RegionChild2,
                               blank=True,
                               null=True,
                               verbose_name=_("commune"))
    status = models.SmallIntegerField(
        verbose_name=_("status"),
        null=True,
        blank=True,
        help_text=_(
            "0 = en création, 1 = en validation, 3 = public, 4 = exporté vers le cahier "
            "spécial"))
    latitude = models.FloatField(null=True,
                                 blank=True,
                                 verbose_name=_("latitude"))
    longitude = models.FloatField(verbose_name=_("longitude"),
                                  null=True,
                                  blank=True)
    slug = models.SlugField(null=True,
                            blank=True,
                            help_text=_("nom formaté pour les URLs"))
    old_id = models.IntegerField(null=True, blank=True)

    ## geodjango magic
    in_geom = models.PointField(
        'shp',
        srid=4326,
        help_text=_("Cliquez sur la carte"),
        null=True,
        blank=True,
    )
    objects = models.GeoManager()

    def as_a_link(self):
        return '<a href="' + self.get_absolute_url(
        ) + '" class="venue">' + self.name + '</a>'

    def get_absolute_url(self):
        from django.core.urlresolvers import reverse
        return reverse('place', args=[self.slug])

    class Meta:
        verbose_name = _('lieu')
        verbose_name_plural = _('lieux')

    def save(self, **kwargs):
        if self.slug is not None:
            from regionfestival.snippets import unique_slugify
            unique_slugify(self, self.name)
        if self.in_geom is not None:
            self.longitude = self.in_geom.x
            self.latitude = self.in_geom.y
            try:
                self.region = RegionChild2.objects.get(
                    boundaries__contains=self.in_geom)
            except:
                pass
        elif self.longitude is not None and self.latitude is not None:
            self.in_geom = 'POINT (' + str(self.latitude) + ' ' + str(
                self.longitude) + ' )'
        super(Lieu, self).save(**kwargs)

    def __str__(self):
        return self.name
Пример #7
0
class FireStation(USGSStructureData):
    """
    Fire Stations.
    """
    service_id = 7

    fdid = models.CharField(max_length=10, null=True, blank=True)
    department = models.ForeignKey(FireDepartment, null=True, blank=True, on_delete=models.SET_NULL)
    station_number = models.IntegerField(null=True, blank=True)
    station_address = models.ForeignKey(Address, null=True, blank=True)
    district = models.MultiPolygonField(null=True, blank=True)
    objects = models.GeoManager()

    @classmethod
    def populate_address(cls):

        us, _ = Country.objects.get_or_create(iso_code='US')
        for obj in cls.objects.filter(station_address__isnull=True, address__isnull=False, zipcode__isnull=False):
            try:
                addr, _ = Address.objects.get_or_create(address_line1=obj.address, city=obj.city,
                                                        state_province=obj.state, postal_code=obj.zipcode,
                                                        country=us, defaults=dict(geom=obj.geom))
            except Address.MultipleObjectsReturned:
                objs = Address.objects.filter(address_line1=obj.address, city=obj.city, state_province=obj.state, postal_code=obj.zipcode,
                                                        country=us)
                import ipdb; ipdb.set_trace()
            obj.station_address = addr
            obj.save()
    @property
    def origin_uri(self):
        """
        This object's URI (from the national map).
        """
        return 'http://services.nationalmap.gov/arcgis/rest/services/structures/MapServer/7/{0}?f=json' \
            .format(self.objectid)

    @classmethod
    def load_data(cls):
        objects = requests.get('http://services.nationalmap.gov/arcgis/rest/services/structures/MapServer/7/query?'
                               'where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&'
                               'spatialRel=esriSpatialRelIntersects&relationParam=&outFields=&returnGeometry=true&'
                               'maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=true&returnCountOnly=false&'
                               'orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&'
                               'gdbVersion=&returnDistinctValues=false&f=json')

        current_ids = set(FireStation.objects.all().values_list('objectid', flat=True))
        object_ids = set(json.loads(objects.content)['objectIds']) - current_ids
        url = 'http://services.nationalmap.gov/arcgis/rest/services/structures/MapServer/7/{0}?f=json'
        us, _ = Country.objects.get_or_create(iso_code='US')

        for object in object_ids:
            try:

                if FireStation.objects.filter(objectid=object):
                    continue

                obj = requests.get(url.format(object))
                obj = json.loads(obj.content)
                data = dict((k.lower(), v) for k, v in obj['feature']['attributes'].iteritems())

                if obj['feature'].get('geometry'):
                    data['geom'] = Point(obj['feature']['geometry']['x'], obj['feature']['geometry']['y'])

                data['loaddate'] = datetime.datetime.fromtimestamp(data['loaddate']/1000.0)
                feat = cls.objects.create(**data)
                feat.save()
                print 'Saved object: {0}'.format(data.get('name'))
                print '{0} Firestations loaded.'.format(FireStation.objects.all().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()

    @property
    def district_area(self):
        """
        Project the district's geometry into north america lambert conformal conic
        Returns km2
        """
        if self.district:
            try:
                return self.district.transform(102009, clone=True).area / 1000000
            except:
                return

    def get_absolute_url(self):
        return reverse('firestation_detail', kwargs=dict(pk=self.id))

    class Meta:
        verbose_name = 'Fire Station'
Пример #8
0
class Map(NamedModel):
    """
    A single thematical map.
    """
    ANONYMOUS = 1
    EDITORS = 2
    OWNER = 3
    PUBLIC = 1
    OPEN = 2
    PRIVATE = 3
    EDIT_STATUS = (
        (ANONYMOUS, _('Everyone can edit')),
        (EDITORS, _('Only editors can edit')),
        (OWNER, _('Only owner can edit')),
    )
    SHARE_STATUS = (
        (PUBLIC, _('everyone (public)')),
        (OPEN, _('anyone with link')),
        (PRIVATE, _('editors only')),
    )
    slug = models.SlugField(db_index=True)
    description = models.TextField(blank=True, null=True, verbose_name=_("description"))
    center = models.PointField(geography=True, verbose_name=_("center"))
    zoom = models.IntegerField(default=7, verbose_name=_("zoom"))
    locate = models.BooleanField(default=False, verbose_name=_("locate"), help_text=_("Locate user on load?"))
    licence = models.ForeignKey(
        Licence,
        help_text=_("Choose the map licence."),
        verbose_name=_('licence'),
        on_delete=models.SET_DEFAULT,
        default=get_default_licence
    )
    modified_at = models.DateTimeField(auto_now=True)
    tilelayer = models.ForeignKey(TileLayer, blank=True, null=True, related_name="maps",  verbose_name=_("background"))
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name="owned_maps", verbose_name=_("owner"))
    editors = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_("editors"))
    edit_status = models.SmallIntegerField(choices=EDIT_STATUS, default=OWNER, verbose_name=_("edit status"))
    share_status = models.SmallIntegerField(choices=SHARE_STATUS, default=PUBLIC, verbose_name=_("share status"))
    settings = DictField(blank=True, null=True, verbose_name=_("settings"))

    objects = models.GeoManager()
    public = PublicManager()

    def get_absolute_url(self):
        return reverse("map", kwargs={'slug': self.slug or "map", 'pk': self.pk})

    def get_anonymous_edit_url(self):
        signer = Signer()
        signature = signer.sign(self.pk)
        return reverse('map_anonymous_edit_url', kwargs={'signature': signature})

    def is_anonymous_owner(self, request):
        if self.owner:
            # edit cookies are only valid while map hasn't owner
            return False
        key, value = self.signed_cookie_elements
        try:
            has_anonymous_cookie = int(request.get_signed_cookie(key, False)) == value
        except ValueError:
            has_anonymous_cookie = False
        return has_anonymous_cookie

    def can_edit(self, user=None, request=None):
        """
        Define if a user can edit or not the instance, according to his account
        or the request.
        """
        can = False
        if request and not self.owner:
            if (getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False)
                    and self.is_anonymous_owner(request)):
                can = True
                if user and user.is_authenticated():
                    # if user is authenticated, attach as owner
                    self.owner = user
                    self.save()
                    msg = _("Your anonymous map has been attached to your account %s" % user)
                    messages.info(request, msg)
        if self.edit_status == self.ANONYMOUS:
            can = True
        elif not user.is_authenticated():
            pass
        elif user == self.owner:
            can = True
        elif self.edit_status == self.EDITORS and user in self.editors.all():
            can = True
        return can

    def can_view(self, request):
        if self.owner is None:
            can = True
        elif self.share_status in [self.PUBLIC, self.OPEN]:
            can = True
        elif request.user == self.owner:
            can = True
        else:
            can = not (self.share_status == self.PRIVATE and request.user not in self.editors.all())
        return can

    @property
    def signed_cookie_elements(self):
        return ('anonymous_owner|%s' % self.pk, self.pk)

    def get_tilelayer(self):
        return self.tilelayer or TileLayer.get_default()

    def clone(self, **kwargs):
        new = self.__class__.objects.get(pk=self.pk)
        new.pk = None
        new.name = u"%s %s" % (_("Clone of"), self.name)
        if "owner" in kwargs:
            # can be None in case of anonymous cloning
            new.owner = kwargs["owner"]
        new.save()
        for editor in self.editors.all():
            new.editors.add(editor)
        for datalayer in self.datalayer_set.all():
            datalayer.clone(map_inst=new)
        return new
Пример #9
0
class Checkin(models.Model):
    time = models.DateTimeField()
    user = models.ForeignKey(User)
    place = models.ForeignKey(Place)
    note = models.TextField()
    objects = gismodels.GeoManager()
Пример #10
0
class Commune(models.Model, GEOFLAManager):
    GEOFLA_DBF_FIELDS = [
        'ID_GEOFLA', 'CODE_COMM', 'INSEE_COM', 'NOM_COMM', 'STATUT',
        'X_CHF_LIEU', 'Y_CHF_LIEU', 'X_CENTROID', 'Y_CENTROID', 'Z_MOYEN',
        'SUPERFICIE', 'POPULATION', 'CODE_CANT', 'CODE_ARR', 'CODE_DEPT',
        'NOM_DEPT', 'CODE_REG', 'NOM_REGION'
    ]
    GEOFLAFIELDS = [
        GFFM('ID_GEOFLA', 'id_geofla', int),
        GFFM('CODE_COMM', 'code_comm', 'to_unicode'),
        GFFM('INSEE_COM', 'insee_com', 'to_unicode'),
        GFFM('NOM_COMM', 'nom_comm', 'to_unicode'),
        GFFM('STATUT', 'statut', 'to_choice', choices=STATUT_COMMUNE),
        GFFM(('X_CHF_LIEU', 'Y_CHF_LIEU'), 'chf_lieu', 'to_point'),
        GFFM(('X_CENTROID', 'Y_CENTROID'), 'centroid', 'to_point'),
        GFFM('Z_MOYEN', 'z_moyen', int),
        GFFM('SUPERFICIE', 'superficie', int),
        GFFM('POPULATION', 'population', float),
    ]
    #GFFM(('CODE_CANT', 'CODE_ARR', 'CODE_DEPT', 'NOM_DEPT'), 'canton',
    #                                'get_instance', instance_class=Canton),]
    id_geofla = models.IntegerField(primary_key=True)
    code_comm = models.CharField(verbose_name=u"Code commune",
                                 null=True,
                                 blank=True,
                                 max_length=3)
    insee_com = models.CharField(verbose_name=u"Code INSEE",
                                 null=True,
                                 blank=True,
                                 max_length=5)
    nom_comm = models.CharField(verbose_name=u"Nom",
                                null=True,
                                blank=True,
                                max_length=50)
    statut = models.CharField(verbose_name=u"Statut",
                              null=True,
                              blank=True,
                              max_length=2,
                              choices=STATUT_COMMUNE)
    chf_lieu = models.PointField(verbose_name=u"Chef lieu",
                                 null=True,
                                 blank=True,
                                 srid=settings.EPSG)
    centroid = models.PointField(verbose_name=u"Centroïde",
                                 null=True,
                                 blank=True,
                                 srid=settings.EPSG)
    z_moyen = models.IntegerField(verbose_name=u"Altitude moyenne (m)",
                                  null=True,
                                  blank=True)
    superficie = models.IntegerField(verbose_name=u"Superficie (ha)",
                                     null=True,
                                     blank=True)
    population = models.FloatField(verbose_name=u"Population (en milliers)",
                                   null=True,
                                   blank=True)
    limite = models.MultiPolygonField(verbose_name=u"Limite",
                                      null=True,
                                      blank=True,
                                      srid=settings.EPSG)
    #canton = models.ForeignKey("Canton", null=True, blank=True)
    objects = models.GeoManager()

    def __unicode__(self):
        return self.nom_comm
Пример #11
0
class Geo(models.Model):
    STATE_TYPE, COUNTY_TYPE, TRACT_TYPE, METRO_TYPE, MICRO_TYPE = range(1, 6)
    METDIV_TYPE, = range(6, 7)
    TYPES = [(STATE_TYPE, 'State'), (COUNTY_TYPE, 'County'),
             (TRACT_TYPE, 'Census Tract'), (METRO_TYPE, 'Metropolitan'),
             (MICRO_TYPE, 'Micropolitan'),
             (METDIV_TYPE, 'Metropolitan Division')]

    geoid = models.CharField(max_length=20, primary_key=True)
    geo_type = models.PositiveIntegerField(choices=TYPES, db_index=True)
    name = models.CharField(max_length=50)

    state = models.CharField(max_length=2, null=True)
    county = models.CharField(max_length=3, null=True)
    tract = models.CharField(max_length=6, null=True)
    csa = models.CharField(max_length=3,
                           null=True,
                           help_text='Combined Statistical Area')
    cbsa = models.CharField(max_length=5,
                            null=True,
                            help_text='Core Based Statistical Area')
    metdiv = models.CharField(max_length=5,
                              null=True,
                              help_text='Metro Division')

    geom = models.MultiPolygonField(srid=4269)

    minlat = models.FloatField()
    maxlat = models.FloatField()
    minlon = models.FloatField()
    maxlon = models.FloatField()
    centlat = models.FloatField()
    centlon = models.FloatField()

    objects = models.GeoManager()

    class Meta:
        index_together = [("geo_type", "minlat", "minlon"),
                          ("geo_type", "minlat", "maxlon"),
                          ("geo_type", "maxlat", "minlon"),
                          ("geo_type", "maxlat", "maxlon"),
                          ("geo_type", "centlat", "centlon"),
                          ("geo_type", "cbsa")]

    def as_geojson(self):
        """Convert this model into a geojson string"""
        geojson = {
            'type': 'Feature',
            'geometry': '$_$',  # placeholder
            'properties': {
                'geoid': self.geoid,
                'geoType': self.geo_type,
                'state': self.state,
                'county': self.county,
                'cbsa': self.cbsa,
                'centlat': self.centlat,
                'centlon': self.centlon
            }
        }
        geojson = json.dumps(geojson)
        return geojson.replace(
            '"$_$"',
            self.geom.simplify(preserve_topology=True).geojson)
Пример #12
0
def create_postal_codes():
    @property
    def parent(self):
        """Returns region if available, otherwise country"""
        return self.region if self.region else self.country

    @property
    def hierarchy(self):
        """Get hierarchy, root first"""
        list = self.parent.hierarchy
        list.append(self)
        return list

    @property
    def names(self):
        """Get a hierarchy of non-null names, root first"""
        return [
            e for e in [
                force_unicode(self.country),
                force_unicode(self.region_0_name),
                force_unicode(self.region_1_name),
                force_unicode(self.region_2_name),
                force_unicode(self.name),
            ] if e
        ]

    @property
    def name_full(self):
        """Get full name including hierarchy"""
        return u', '.join(reversed(self.names))

    postal_codes = {}
    for country in settings.postal_codes:
        name_format = "{}" + country
        name = name_format.format('PostalCode')
        postal_codes[country] = create_model(
            name=name,
            fields={
                'country':
                models.ForeignKey(Country,
                                  related_name='postal_codes_' + country),
                'code':
                models.CharField(max_length=20, db_index=True),
                'name':
                models.CharField(max_length=200, db_index=True),
                'region_0_name':
                models.CharField(max_length=100,
                                 db_index=True,
                                 verbose_name="region 0 name (state)"),
                'region_1_name':
                models.CharField(max_length=100,
                                 db_index=True,
                                 verbose_name="region 1 name (county)"),
                'region_2_name':
                models.CharField(max_length=100,
                                 db_index=True,
                                 verbose_name="region 2 name (community)"),
                'region':
                models.ForeignKey(Region,
                                  null=True,
                                  blank=True,
                                  related_name='postal_codes_' + country),
                'location':
                models.PointField(),
                'objects':
                models.GeoManager(),
                'parent':
                parent,
                'hierarchy':
                hierarchy,
                'names':
                names,
                'name_full':
                name_full,
                '__unicode__':
                lambda self: force_unicode(self.code),
            },
            app_label='cities',
            module='cities.models',
            options={
                'db_table':
                'cities_' + un_camel(name),
                'verbose_name':
                un_camel(name).replace('_', ' '),
                'verbose_name_plural':
                un_camel(name_format.format('PostalCodes')).replace('_', ' '),
            },
        )
    return postal_codes
Пример #13
0
class InformationDesk(models.Model):

    name = models.CharField(verbose_name=_(u"Title"),
                            max_length=256,
                            db_column='nom')
    type = models.ForeignKey(InformationDeskType,
                             verbose_name=_(u"Type"),
                             related_name='desks',
                             db_column='type')
    description = models.TextField(verbose_name=_(u"Description"),
                                   blank=True,
                                   db_column='description',
                                   help_text=_(u"Brief description"))
    phone = models.CharField(verbose_name=_(u"Phone"),
                             max_length=32,
                             blank=True,
                             null=True,
                             db_column='telephone')
    email = models.EmailField(verbose_name=_(u"Email"),
                              max_length=256,
                              db_column='email',
                              blank=True,
                              null=True)
    website = models.URLField(verbose_name=_(u"Website"),
                              max_length=256,
                              db_column='website',
                              blank=True,
                              null=True)
    photo = models.FileField(verbose_name=_(u"Photo"),
                             upload_to=settings.UPLOAD_DIR,
                             db_column='photo',
                             max_length=512,
                             blank=True,
                             null=True)

    street = models.CharField(verbose_name=_(u"Street"),
                              max_length=256,
                              blank=True,
                              null=True,
                              db_column='rue')
    postal_code = models.CharField(verbose_name=_(u"Postal code"),
                                   max_length=8,
                                   blank=True,
                                   null=True,
                                   db_column='code')
    municipality = models.CharField(verbose_name=_(u"Municipality"),
                                    blank=True,
                                    null=True,
                                    max_length=256,
                                    db_column='commune')

    geom = models.PointField(verbose_name=_(u"Emplacement"),
                             db_column='geom',
                             blank=True,
                             null=True,
                             srid=settings.SRID,
                             spatial_index=False)

    objects = models.GeoManager()

    class Meta:
        db_table = 't_b_renseignement'
        verbose_name = _(u"Information desk")
        verbose_name_plural = _(u"Information desks")
        ordering = ['name']

    def __unicode__(self):
        return self.name

    @property
    def description_strip(self):
        """Used in trek public template.
        """
        nobr = re.compile(r'(\s*<br.*?>)+\s*', re.I)
        newlines = nobr.sub("\n", self.description)
        return smart_plain_text(newlines)

    @property
    def serializable_type(self):
        return {
            'id': self.type.id,
            'label': self.type.label,
            'pictogram': self.type.pictogram.url,
        }

    @property
    def latitude(self):
        if self.geom:
            api_geom = self.geom.transform(settings.API_SRID, clone=True)
            return api_geom.y
        return None

    @property
    def longitude(self):
        if self.geom:
            api_geom = self.geom.transform(settings.API_SRID, clone=True)
            return api_geom.x
        return None

    @property
    def thumbnail(self):
        if not self.photo:
            return None
        thumbnailer = get_thumbnailer(self.photo)
        try:
            return thumbnailer.get_thumbnail(aliases.get('thumbnail'))
        except InvalidImageFormatError:
            logger.warning(
                _("Image %s invalid or missing from disk.") % self.photo)
            return None

    @property
    def photo_url(self):
        thumbnail = self.thumbnail
        if not thumbnail:
            return None
        return os.path.join(settings.MEDIA_URL, thumbnail.name)
Пример #14
0
class Place(models.Model):
    #BUG - why id is NULL?
    #name&position - уникальный индификатор
    name = models.CharField(max_length=128, verbose_name=u"название")
    position = models.PointField(verbose_name=u"координаты")
    objects = models.GeoManager()

    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this place should be treated as '
            'active. Unselect this instead of place has no owner too long'
            ' (by engine initiate).'))
    is_in_engine = models.BooleanField(
        _('create in engine'),
        default=False,
        help_text=_('After creation place in db, place is created in engine.'
                    'If it be done successfully - tis field will be true'))

    date = models.DateTimeField(default=timezone.now,
                                verbose_name=u"дата создания")
    date_is_active = models.DateTimeField(default=timezone.now,
                                          verbose_name=u"дата активации")
    address = models.CharField(
        max_length=128,
        null=True,
        blank=True,
        verbose_name=u"адрес",
    )
    crossStreet = models.CharField(
        max_length=128,
        null=True,
        blank=True,
        verbose_name=u"пересечение улиц",
    )
    contact = models.CharField(
        max_length=512,
        null=True,
        blank=True,
        verbose_name=u"контакты",
    )
    city_id = models.IntegerField(
        db_index=True,
        null=False,
        blank=False,
        verbose_name=u"идентификатор в GeoNames",
    )

    fsq_id = models.CharField(
        max_length=24,
        null=True,
        blank=True,
        verbose_name=u"идентификатор в Foursquare",
    )
    foursquare_icon_prefix = models.CharField(
        max_length=128,
        null=True,
        blank=True,
        verbose_name=u"префикс пиктограммы категории в Foursquare")
    foursquare_icon_suffix = models.CharField(
        max_length=16,
        null=True,
        blank=True,
        verbose_name=u"суффикс (расширение) пиктограммы категории в Foursquare"
    )

    def longitude(self):
        return self.position.x

    def latitude(self):
        return self.position.y

    def foursquare_details_url(self):
        return "https://foursquare.com/v/%s" % self.fsq_id

    def get_string_date(self):
        return get_string_date(self.date_is_active)

    def create_in_engine(self):
        self.is_in_engine = True
        self.save()

    def __unicode__(self):
        return u"%s" % self.name + (self.address and
                                    (u", %s" % self.address) or u"")

    class Meta:
        unique_together = (
            'position',
            'name',
        )
        verbose_name = _('place')
        verbose_name_plural = _('places')
        ordering = ("name", )
Пример #15
0
class City(models.Model):
    name = models.CharField(max_length=30)
    point = models.PointField()
    objects = models.GeoManager()
    def __str__(self): return self.name
Пример #16
0
class GADM(models.Model):
    id_0 = models.IntegerField()
    iso = models.CharField(max_length=3)
    name_engli = models.CharField(max_length=50)
    name_iso = models.CharField(max_length=54)
    name_fao = models.CharField(max_length=50)
    name_local = models.CharField(max_length=54)
    name_obsol = models.CharField(max_length=150)
    name_varia = models.CharField(max_length=160)
    name_nonla = models.CharField(max_length=50)
    name_frenc = models.CharField(max_length=50)
    name_spani = models.CharField(max_length=50)
    name_russi = models.CharField(max_length=50)
    name_arabi = models.CharField(max_length=50)
    name_chine = models.CharField(max_length=50)
    waspartof = models.CharField(max_length=100)
    contains = models.CharField(max_length=50)
    sovereign = models.CharField(max_length=40)
    iso2 = models.CharField(max_length=4)
    www = models.CharField(max_length=2)
    fips = models.CharField(max_length=6)
    ison = models.FloatField()
    validfr = models.CharField(max_length=12)
    validto = models.CharField(max_length=10)
    pop2000 = models.FloatField()
    sqkm = models.FloatField()
    popsqkm = models.FloatField()
    unregion1 = models.CharField(max_length=254)
    unregion2 = models.CharField(max_length=254)
    developing = models.FloatField()
    cis = models.FloatField()
    transition = models.FloatField()
    oecd = models.FloatField()
    wbregion = models.CharField(max_length=254)
    wbincome = models.CharField(max_length=254)
    wbdebt = models.CharField(max_length=254)
    wbother = models.CharField(max_length=254)
    ceeac = models.FloatField()
    cemac = models.FloatField()
    ceplg = models.FloatField()
    comesa = models.FloatField()
    eac = models.FloatField()
    ecowas = models.FloatField()
    igad = models.FloatField()
    ioc = models.FloatField()
    mru = models.FloatField()
    sacu = models.FloatField()
    uemoa = models.FloatField()
    uma = models.FloatField()
    palop = models.FloatField()
    parta = models.FloatField()
    cacm = models.FloatField()
    eurasec = models.FloatField()
    agadir = models.FloatField()
    saarc = models.FloatField()
    asean = models.FloatField()
    nafta = models.FloatField()
    gcc = models.FloatField()
    csn = models.FloatField()
    caricom = models.FloatField()
    eu = models.FloatField()
    can = models.FloatField()
    acp = models.FloatField()
    landlocked = models.FloatField()
    aosis = models.FloatField()
    sids = models.FloatField()
    islands = models.FloatField()
    ldc = models.FloatField()
    geom = models.MultiPolygonField(srid=4326, null=True)
    objects = models.GeoManager()

    class Meta:
        verbose_name = 'Country'
        verbose_name_plural = 'Countries'

    @staticmethod
    def is_valid_point(country_name, point, margin_km=50):
        """
        Checks if the point is within county's borders with margin of 'margin_km' kilometers from its borders.

        Parameters
        ----------
        country_name : str
        point : tuple
        margin_km : int

        Returns
        -------
        status : bool
        """
        pnt = Point(*point, srid=4326)
        country = GADM.objects.filter(name_engli__iexact=country_name)
        if not country:
            return False
        if country.distance(pnt).get(
                name_engli__iexact=country_name).distance.km < margin_km:
            return True
        return False
Пример #17
0
class Location(models.Model):
    """Model for school locations in Chicago
    """
    EMPTY = ''
    NONE = 'None'
    LICENSED = 'Licensed'
    BRONZE = 'Bronze'
    SILVER = 'Silver'
    GOLD = 'Gold'

    Q_RATING_CHOICES = (
        (EMPTY, ugettext_lazy('Select a rating')),
        (NONE, ugettext_lazy('None')),
        (LICENSED, ugettext_lazy('Licensed')),
        (BRONZE, ugettext_lazy('Bronze')),
        (SILVER, ugettext_lazy('Silver')),
        (GOLD, ugettext_lazy('Gold')),
    )

    LOCATION_TYPE_CHOICES = (
        (0, 'Normal Location'),
        (1, 'Application Site'),
    )

    HIGH = 'High'
    MEDIUM = 'Medium'
    LOW = 'Low'

    AVAILABILITY_CHOICES = (
        (HIGH, ugettext_lazy('High')),
        (MEDIUM, ugettext_lazy('Medium')),
        (LOW, ugettext_lazy('Low')),
    )

    ecm_key = models.IntegerField('ECM Key', default=0, blank=True)
    site_name = models.CharField('Site Name', max_length=100)
    site_type = models.IntegerField('Site Type',
                                    default=0,
                                    choices=LOCATION_TYPE_CHOICES)
    address = models.CharField('Address', max_length=75)
    city = models.CharField('City', max_length=75)
    state = models.CharField('State', max_length=2)
    zip = models.CharField('Zip Code', max_length=10)
    neighborhood = models.ForeignKey('Neighborhood', null=True)
    phone = models.CharField(ugettext_lazy('Phone Number'),
                             max_length=20,
                             blank=True)
    q_rating = models.CharField(ugettext_lazy('Quality Rating'),
                                choices=Q_RATING_CHOICES,
                                max_length=10,
                                blank=True)
    url = models.CharField(ugettext_lazy('Website'),
                           max_length=256,
                           blank=True)
    q_stmt = models.TextField(ugettext_lazy('Description'), blank=True)
    enrollment = models.TextField(ugettext_lazy('Enrollment Process'),
                                  blank=True)
    accred = models.CharField(ugettext_lazy('Accreditation'),
                              max_length=100,
                              blank=True)
    prg_hours = models.CharField(ugettext_lazy('Program Hours'),
                                 max_length=50,
                                 blank=True)
    is_age_lt_3 = models.NullBooleanField(ugettext_lazy('Ages 0 - 3'))
    is_age_gt_3 = models.NullBooleanField(ugettext_lazy('Ages 3 - 5'))
    is_full_day = models.NullBooleanField(ugettext_lazy('Full Day'))
    is_part_day = models.NullBooleanField(ugettext_lazy('Part Day'))
    is_school_year = models.NullBooleanField(ugettext_lazy('School Year'))
    is_full_year = models.NullBooleanField(ugettext_lazy('Full Year'))
    ages = models.CharField(ugettext_lazy('Ages Served'),
                            max_length=50,
                            blank=True)
    is_full_week = models.NullBooleanField(ugettext_lazy('Full Week'))
    is_part_week = models.NullBooleanField(ugettext_lazy('Part Week'))
    language_1 = models.CharField('Language 1 (other than English)',
                                  max_length=50,
                                  blank=True)
    language_2 = models.CharField('Language 2 (other than English)',
                                  max_length=50,
                                  blank=True)
    language_3 = models.CharField('Language 3 (other than English)',
                                  max_length=50,
                                  blank=True)
    is_community_based = models.NullBooleanField(
        ugettext_lazy('Community Based'))
    is_cps_based = models.NullBooleanField(ugettext_lazy('CPS Based'))
    is_home_visiting = models.NullBooleanField(
        ugettext_lazy('Offers Home Visiting'))
    accept_ccap = models.NullBooleanField(ugettext_lazy('Accepts CCAP'))
    is_hs = models.NullBooleanField(ugettext_lazy('Head Start'))
    is_ehs = models.NullBooleanField(ugettext_lazy('Early Head Start'))
    open_house = models.TextField(ugettext_lazy('Open House'), blank=True)
    curriculum = models.TextField(ugettext_lazy('Curriculum'), blank=True)
    email = models.EmailField(blank=True)

    # Keeps track of whether or not new locations have been approved by the admin
    accepted = models.BooleanField(ugettext_lazy('Approved'), default=False)

    # ECM alottment status, classroom availability
    availability = models.CharField(ugettext_lazy('Availability'),
                                    choices=AVAILABILITY_CHOICES,
                                    max_length=10,
                                    blank=True)

    # To get these placeholder fields to show up in the UI, replace
    # 'Placeholder 1' and 'Placeholder 2' in the lines below with
    # real labels, and add 'placeholder_1' and 'placeholder_2' to the
    # 'display_include' list. Also, in admin.py, browse to the
    # LocationAdmin class and add the appropriate entries to the
    # fieldsets list.
    placeholder_1 = models.TextField('Placeholder 1', blank=True)
    placeholder_2 = models.TextField('Placeholder 2', blank=True)

    geom = models.PointField('Geometry', srid=4326, null=True)
    objects = models.GeoManager()

    # List of simple/boolean fields that should be displayed by Location renderers/views
    display_include = {
        'ages',
        'accred',
        'accept_ccap',
        'is_home_visiting',
        'is_hs',
        'is_ehs',
        'is_community_based',
        'is_cps_based',
        'open_house',
        'curriculum',
    }

    # List of fields that should be hidden when left blank
    hide_if_none = {
        'open_house',
        'curriculum',
    }

    display_order = dict((k, v) for v, k in enumerate([
        'open_house', 'accred', 'ages', 'description', 'enrollment',
        'duration_hours', 'weekday_availability', 'languages', 'program_info',
        'curriculum', 'quality_rating'
    ]))

    q_rating_translations = [
        ugettext_lazy('None'),
        ugettext_lazy('Licensed'),
        ugettext_lazy('Bronze'),
        ugettext_lazy('Silver'),
        ugettext_lazy('Gold')
    ]

    def __unicode__(self):
        return unicode(self.site_name)

    def verbose_name(self, field):
        """
        Given the name of field, returns the verbose_name property for it
        """
        return unicode(self._meta.get_field_by_name(field)[0].verbose_name)

    @property
    def is_enrollment(self):
        if self.site_type == 1:
            return True
        else:
            return False

    def combine_languages(self):
        lang_list = [
            lang for lang in self.language_1, self.language_2, self.language_3
            if lang
        ]
        languages = ", ".join(lang_list)
        return languages

    def combine_other_features(self):
        other_features = ''
        return other_features

    @staticmethod
    def get_filter_fields():
        """
        Returns all boolean fields that should be used for filtering Location objects

        This method does not use a static list of names, but rather inspects
        the meta class attached to the model to introspect on the field types.
        This also has the benefit of providing the verbose name of the field.
        """

        # TODO: This relies on fields being ordered in the fields object in the
        # same order they're defined above.  This is probably a sketchy assumption.
        exclude = ['is_montessori', 'is_special_ed']

        fields = []
        for field in Location._meta.fields:
            if (field.get_internal_type() == 'NullBooleanField'
                    and not field.get_attname() in exclude):
                fields.append((
                    field.get_attname(),
                    _(field.verbose_name),
                ))

        return fields

    def get_boolean_fieldnames(self):
        """
        Extracts list of boolean field names from model
        """
        fields = self._meta.fields
        return [
            field.name for field in fields
            if field.get_internal_type() == 'NullBooleanField'
        ]

    def is_true_bool_field(self, field):
        """
        Returns true if field is a boolean field and self.field is True
        """
        fname = field.get_attname()
        return (field.get_internal_type() == 'NullBooleanField'
                and getattr(self, fname))

    def is_simple_field(self, field):
        """
        Returns true if field is of type CharField or TextField
        """
        ftype = field.get_internal_type()
        return ((ftype == 'CharField' or ftype == 'TextField'))

    def get_context_dict(self, short=False):
        """Gets a context dictionary for rendering this object in templates

        Performs a bunch of cleanup and filtering logic to format fields appropriately and
        remove useless info

        :param short: If true, a shorter version of the dict will be returned
        """
        # Fix some ugly data
        if self.site_name.isupper():
            self.site_name = title(self.site_name)
        if self.address.isupper():
            self.address = title(self.address)
        if self.city.isupper():
            self.city = title(self.city)

        item = {
            'address': self.address,
            'city': self.city,
            'site_name': self.site_name,
            'zip': self.zip,
            'url': self.url,
            'state': self.state,
            'key': self.pk,
            'email': self.email,
            'type': self.site_type,
            'full_day': self.is_full_day,
            'part_day': self.is_part_day,
            'age_lt_3': self.is_age_lt_3,
            'age_gt_3': self.is_age_gt_3,
            'site_type': self.site_type,
            'is_enrollment': self.is_enrollment,
            'duration_hours': self.prg_hours,
        }

        # simple fields to present -- these are the attributes that have text content
        sfields = []

        # boolean fields to present -- these are the attributes that are set to True
        bfields = []

        # Fields to include in Affiliation aggregate field
        affiliation_fields = [
            self._meta.get_field_by_name(name)[0] for name in [
                'is_home_visiting', 'is_community_based', 'is_cps_based',
                'is_hs', 'is_ehs'
            ]
        ]
        program_fields = [
            self._meta.get_field_by_name(name)[0]
            for name in ['is_full_year', 'is_school_year']
        ]

        week_fields = [
            self._meta.get_field_by_name(name)[0] for name in
            ['is_full_week', 'is_part_week', 'is_full_day', 'is_part_day']
        ]

        aff_field_names = {f.get_attname() for f in affiliation_fields}

        for field in self._meta.fields:
            fname = field.get_attname()

            if not fname in self.display_include or fname in aff_field_names:
                continue

            if self.is_true_bool_field(field):
                bfields.append(field.verbose_name)
            elif self.is_simple_field(field):
                value = field.value_from_object(self)
                hide_field = fname in self.hide_if_none and not value
                if not hide_field:
                    kv = {
                        'key': fname,
                        'fieldname': _(field.verbose_name),
                        'value': value if value else _('None')
                    }
                    sfields.append(kv)

        affiliation_values = [
            self.verbose_name(aff.get_attname()) for aff in affiliation_fields
            if aff.value_from_object(self)
        ]
        sfields.append({
            'key':
            'program_info',
            'fieldname':
            _('Program Information'),
            'value':
            ', '.join(affiliation_values) if affiliation_values else _('None')
        })

        # Combine Languages
        lang_list = [
            lang for lang in self.language_1, self.language_2, self.language_3
            if lang
        ]
        languages = ", ".join(lang_list)
        if languages != '':
            sfields.append({
                'key': 'languages',
                'fieldname': _('Languages'),
                'value': languages
            })

        # Program Duration/Hours
        program_values = [
            self.verbose_name(prg.get_attname()) for prg in program_fields
            if prg.value_from_object(self)
        ]
        program_hours = self.prg_hours if self.prg_hours else _(
            "No Hours Listed")
        program_values.append(program_hours)
        sfields.append({
            'key':
            'duration_hours',
            'fieldname':
            _('Duration and Hours'),
            'value':
            ', '.join(program_values) if program_values else _('None')
        })

        # Weekday Avaialability
        week_values = [
            self.verbose_name(wk.get_attname()) for wk in week_fields
            if wk.value_from_object(self)
        ]
        sfields.append({
            'key':
            'weekday_availability',
            'fieldname':
            _('Weekday Availability'),
            'value':
            ', '.join(week_values) if week_values else _('None')
        })

        # Quality Rating
        # default empty db entry to coming soon so we don't have to modify code when CEL chooses
        #   to implement this. No q_rating is explicitly set as 'None' in the database and will
        #   be properly displayed in the UI as long as the db field is set to 'None'
        # key for displayed image, not to be translated
        item['quality'] = self.q_rating.lower() or 'none'
        # translatable displayed text
        q_rating = self.q_rating or 'Coming Soon'
        sfields.append({
            'key': 'quality_rating',
            'fieldname': _('Quality Rating'),
            'value': _(q_rating)
        })

        # Phone
        phone = {
            'fieldname': _('Phone Number'),
            'number': nicephone(self.phone)
        }

        # Position
        position = {'lng': self.geom[0], 'lat': self.geom[1]}

        # Quality Statement
        if self.q_stmt and not short:
            sfields.append({
                'key': 'description',
                'fieldname': _('Description'),
                'value': self.q_stmt
            })

        bfields.sort()
        sfields.sort(key=lambda a: self.display_order[a['key']])

        # Translation
        # Adding a dictionary with strings that need to be translated in the handlebars template
        # This way we can do this with django and not have to worry about making a separate
        # handlebars helper
        trans_dict = {
            'more': _('More'),
            'website': _('Website'),
            'directions': _('Directions'),
            'share': _('Share'),
            'qrisrating': _('QRIS Rating'),
            'contact': _('Compare and Apply'),
            'more_info': _('More Info'),
            'serves03': _('Serves ages 0 - 3'),
            'serves35': _('Serves ages 3 - 5'),
            'serves05': _('Serves ages 0 - 3, 3 - 5'),
            'full_day': _('Full Day'),
            'part_day': _('Part Day')
        }

        # More information for tooltip icon
        accreditation = ['Accredited'] if self.accred != 'None' else []
        accreditation.append('School' if self.is_cps_based else 'Center')

        # Tooltips - necessary for translations in handlebars template
        tooltip = {
            'directions': _('Directions from Google'),
            'moreinfo': _('Click to show more information'),
            'star': _('Click to save to your list'),
            'unstar': _('Click to remove from your list'),
            'accreditation': ' '.join(accreditation),
            'quality': _(q_rating)
        }

        return {
            'item': item,
            'phone': phone,
            'sfields': sfields,
            'bfields': {
                'fieldname': _('Other Features'),
                'values': bfields
            },
            'position': position,
            'translations': trans_dict,
            'tooltip': tooltip
        }

    def val_or_empty(self, field, f=(lambda x: x)):
        """
        Returns a pretty string representing the value of a field if it's present, otherwise an
        empty string.  The pretty string ends in a newline.
        field:  string with the name of a field on this model
        f:      optional rendering function.  It's given the value of the field, modifies it, and
                returns the result.  Default returns its input
        """
        val = self.__dict__[field]
        return ("%s: %s\n" % (self.verbose_name(field), f(val))) if val else ""

    def save(self, *args, **kwargs):
        """ Override for Model.save()
        Overrides Location.save(). Provides the additional functionality of updating the Neighborhood
        of the Location before the save.
        """
        if self.geom is not None:
            neighborhoods = Neighborhood.objects.filter(
                boundary__intersects=self.geom)
            if len(neighborhoods):
                self.neighborhood = neighborhoods[0]

        super(Location, self).save(*args, **kwargs)
Пример #18
0
class Instance(models.Model):
    """
    Each "Tree Map" is a single instance
    """
    name = models.CharField(max_length=255, unique=True)

    url_name = models.CharField(
        max_length=255,
        unique=True,
        validators=[
            reserved_name_validator,
            RegexValidator(
                r'^%s$' % URL_NAME_PATTERN,
                trans('Must start with a letter and may only contain '
                      'letters, numbers, or dashes ("-")'),
                trans('Invalid URL name'))
        ])
    """
    Basemap type     Basemap data
    ------------     -----------------
    Google           Google_API_Key
    Bing             Bing_API_Key
    TMS              TMS URL with {x},{y},{z}
    """
    basemap_type = models.CharField(max_length=255,
                                    choices=(("google", "Google"), ("bing",
                                                                    "Bing"),
                                             ("tms", "Tile Map Service")),
                                    default="google")
    basemap_data = models.CharField(max_length=255, null=True, blank=True)
    """
    The current database revision for the instance

    This revision is used to determine if tiles should be cached.
    In particular, the revision has *no* effect on the actual
    data.

    Generally we make tile requests like:
    http://tileserver/tile/{layer}/{rev}/{Z}/{Y}/{X}

    There is a database trigger that updates the
    revision whenever an edit to a geometry field is made
    so you don't have to worry about it.

    You should *not* edit this field.
    """
    geo_rev = models.IntegerField(default=1)

    eco_benefits_conversion = models.ForeignKey('BenefitCurrencyConversion',
                                                null=True,
                                                blank=True)
    """ Center of the map when loading the instance """
    bounds = models.MultiPolygonField(srid=3857)
    """
    Override the center location (which is, by default,
    the centroid of "bounds"
    """
    center_override = models.PointField(srid=3857, null=True, blank=True)

    default_role = models.ForeignKey('Role', related_name='default_role')

    users = models.ManyToManyField('User',
                                   through='InstanceUser',
                                   null=True,
                                   blank=True)

    boundaries = models.ManyToManyField('Boundary', null=True, blank=True)
    """
    Config contains a bunch of config variables for a given instance
    these can be accessed via per-config properties such as
    `advanced_search_fields`. Note that it is a DotDict, and so supports
    get() with a dotted key and a default, e.g.
        instance.config.get('fruit.apple.type', 'delicious')
    as well as creating dotted keys when no keys in the path exist yet, e.g.
        instance.config = DotDict({})
        instance.config.fruit.apple.type = 'macoun'
    """
    config = JSONField(blank=True)

    is_public = models.BooleanField(default=False)

    logo = models.ImageField(upload_to='logos', null=True, blank=True)

    itree_region_default = models.CharField(max_length=20,
                                            null=True,
                                            blank=True,
                                            choices=ITREE_REGION_CHOICES)

    objects = models.GeoManager()

    def __unicode__(self):
        return self.name

    def _make_config_property(prop, default=None):
        def get_config(self):
            return self.config.get(prop, default)

        def set_config(self, value):
            self.config[prop] = value

        return property(get_config, set_config)

    mobile_search_fields = _make_config_property('mobile_search_fields',
                                                 DEFAULT_MOBILE_SEARCH_FIELDS)

    mobile_api_fields = _make_config_property('mobile_api_fields',
                                              DEFAULT_MOBILE_API_FIELDS)

    date_format = _make_config_property('date_format', settings.DATE_FORMAT)

    short_date_format = _make_config_property('short_date_format',
                                              settings.SHORT_DATE_FORMAT)

    scss_variables = _make_config_property('scss_variables')

    map_feature_types = _make_config_property('map_feature_types', ['Plot'])

    @property
    def advanced_search_fields(self):
        # TODO pull from the config once users have a way to set search fields

        from treemap.util import to_object_name

        # if we come to support more udfc searches, we can add them here.
        udfc_models = ['Tree', 'Plot']
        udfc_names = ['Stewardship', 'Alerts']

        # must inflate object so that template can look for keys
        empty_udfc = {
            to_object_name(n_k): {
                to_object_name(m_k): {
                    'fields': [],
                    'udfd': None
                }
                for m_k in udfc_models
            }
            for n_k in udfc_names
        }

        if not self.feature_enabled('advanced_search_filters'):
            return {
                'standard': [],
                'missing': [],
                'display': [],
                'udfc': empty_udfc
            }

        from treemap.models import MapFeature  # prevent circular import
        fields = {
            'standard': [{
                'identifier': 'tree.diameter',
                'search_type': 'RANGE'
            }, {
                'identifier': 'tree.date_planted',
                'search_type': 'RANGE'
            }],
            'display': [{
                'model': 'Tree',
                'label': 'Show trees'
            }, {
                'model': 'EmptyPlot',
                'label': 'Show empty planting sites'
            }],
            'missing': [{
                'identifier': 'species.id',
                'label': 'Show missing species',
                'search_type': 'ISNULL',
                'value': 'true'
            }, {
                'identifier': 'tree.diameter',
                'label': 'Show missing trunk diameter',
                'search_type': 'ISNULL',
                'value': 'true'
            }, {
                'identifier': 'mapFeaturePhoto.id',
                'label': 'Show missing photos',
                'search_type': 'ISNULL',
                'value': 'true'
            }],
        }

        def make_display_filter(feature_name):
            Feature = MapFeature.get_subclass(feature_name)
            if hasattr(Feature, 'display_name_plural'):
                plural = Feature.display_name_plural
            else:
                plural = Feature.display_name + 's'
            return {'label': 'Show %s' % plural.lower(), 'model': feature_name}

        fields['display'] += [
            make_display_filter(feature_name)
            for feature_name in self.map_feature_types
            if feature_name != 'Plot'
        ]

        # It makes styling easier if every field has an identifier
        num = 0
        for filters in fields.itervalues():
            for field in filters:
                field['id'] = "%s_%s" % (field.get('identifier', ''), num)
                num += 1

        # prevent circular import
        from treemap.udf import UserDefinedFieldDefinition

        udfds = UserDefinedFieldDefinition.objects.filter(
            instance=self, name__in=udfc_names, model_type__in=udfc_models)

        udfc = deepcopy(empty_udfc)

        for udfd in udfds:
            udfd_info = {
                'udfd': udfd,
                'fields': udfd.datatype_dict[0]['choices']
            }
            name_dict = udfc[to_object_name(udfd.name)]
            name_dict[to_object_name(udfd.model_type)] = udfd_info

        fields['udfc'] = udfc

        return fields

    @property
    def supports_resources(self):
        """
        Determine whether this instance has multiple map feature
        types (plots + "resources") or not.
        """
        n = len(self.map_feature_types)
        return n > 1

    @property
    def extent_as_json(self):
        boundary = self.bounds.boundary
        xmin, ymin, xmax, ymax = boundary.extent

        return json.dumps({
            'xmin': xmin,
            'ymin': ymin,
            'xmax': xmax,
            'ymax': ymax
        })

    @property
    def center(self):
        return self.center_override or self.bounds.centroid

    @property
    def geo_rev_hash(self):
        return hashlib.md5(str(self.geo_rev)).hexdigest()

    @property
    def center_lat_lng(self):
        return self.center.transform(4326, clone=True)

    @property
    def factor_conversions(self):
        """
        Returns a dict for use in eco.py Benefits from eco_benefits_conversion
        """
        benefits_conversion = self.eco_benefits_conversion
        if benefits_conversion:
            return benefits_conversion.get_factor_conversions_config()
        else:
            return None

    @property
    def scss_query_string(self):
        scss_vars = ({k: val
                      for k, val in self.scss_variables.items()
                      if val} if self.scss_variables else {})
        return urlencode(scss_vars)

    @property
    def static_page_names(self):
        from treemap.models import StaticPage  # prevent circular import

        built_in_names = StaticPage.built_in_names()

        custom_names = [
            page.name for page in StaticPage.objects.filter(
                instance=self).exclude(name__in=built_in_names)
        ]

        names = built_in_names + custom_names

        return names

    def itree_regions(self):
        from treemap.models import ITreeRegion

        if self.itree_region_default:
            regions = [self.itree_region_default]
        else:
            regions = ITreeRegion.objects.filter(
                geometry__intersects=self.bounds)

        return regions

    def has_itree_region(self):
        from treemap.models import ITreeRegion  # prevent circular import
        intersecting_regions = (ITreeRegion.objects.filter(
            geometry__intersects=self.bounds))

        return bool(self.itree_region_default) or intersecting_regions.exists()

    def is_accessible_by(self, user):
        try:
            if self.is_public:
                return True

            # Extension point
            if hasattr(user, 'is_super_admin') and user.is_super_admin():
                return True

            # If a user is not logged in, trying to check
            # user=user raises a type error so I am checking
            # pk instead
            self.instanceuser_set.get(user__pk=user.pk)
            return True
        except ObjectDoesNotExist:
            return False

    def scope_model(self, model):
        qs = model.objects.filter(instance=self)
        return qs

    def feature_enabled(self, feature):
        # Delayed import to prevent circular imports
        from treemap.plugin import feature_enabled
        return feature_enabled(self, feature)

    def seed_with_dummy_default_role(self):
        """
        Instances need roles and roles needs instances... crazy stuff
        we're going to create the needed role below however, we'll temporarily
        use a 'dummy role'. The dummy role has no instance.
        """
        from treemap.audit import Role
        dummy_roles = Role.objects.filter(instance__isnull=True)
        if len(dummy_roles) == 0:
            dummy_role = Role.objects.create(name='empty', rep_thresh=0)
        else:
            dummy_role = dummy_roles[0]

        self.default_role = dummy_role

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

        self.url_name = self.url_name.lower()

        super(Instance, self).save(*args, **kwargs)
Пример #19
0
class USGSStructureData(models.Model):
    """
    Models structure data from the USGS National Map.

    Schema from: http://services.nationalmap.gov/arcgis/rest/services/structures/MapServer/1?f=json
    """
    DATA_SECURITY_CHOICES = [(0, 'Unknown'),
                             (1, 'Top Secret'),
                             (2, 'Secret'),
                             (3, 'Confidential'),
                             (4, 'Restricted'),
                             (5, 'Unclassified'),
                             (6, 'Sensitive')]

    DISTRIBUTION_POLICY_CHOICES = [('A1', 'Emergency Service Provider - Internal Use Only'),
                                   ('A2', 'Emergency Service Provider - Bitmap Display Via Web'),
                                   ('A3', 'Emergency Service Provider - Free Distribution to Third Parties'),
                                   ('A4', 'Emergency Service Provider - Free Distribution to Third Parties Via'
                                          ' Internet'),
                                   ('B1', 'Government Agencies or Their Delegated Agents - Internal Use Only'),
                                   ('B2', 'Government Agencies or Their Delegated Agents - Bitmap Display Via Web'),
                                   ('B3', 'Government Agencies or Their Delegated Agents - Free Distribution to Third'
                                          ' Parties'),
                                   ('B4', 'Government Agencies or Their Delegated Agents - Free Distribution to Third'
                                          ' Parties Via Internet'),
                                   ('C1', 'Other Public or Educational Institutions - Internal Use Only'),
                                   ('C2', 'Other Public or Educational Institutions - Bitmap Display Via Web'),
                                   ('C3', 'Other Public or Educational Institutions - Free Distribution to Third'
                                          ' Parties'),
                                   ('C4', 'Other Public or Educational Institutions - Free Distribution to Third'
                                          ' Parties Via Internet'),
                                   ('D1', 'Data Contributors - Internal Use Only'), ('D2', 'Data Contributors - '
                                                                                           'Bitmap Display Via Web'),
                                   ('D3', 'Data Contributors - Free Distribution to Third Parties'),
                                   ('D4', 'Data Contributors - Free Distribution to Third Parties Via Internet'),
                                   ('E1', 'Public Domain - Internal Use Only'), ('E2', 'Public Domain - Bitmap'
                                                                                       ' Display Via Web'),
                                   ('E3', 'Public Domain - Free Distribution to Third Parties'),
                                   ('E4', 'Public Domain - Free Distribution to Third Parties Via Internet')]

    FCODE_CHOICES = [(81000, 'Transportation Facility'),
                     (81006, 'Airport Terminal'),
                     (81008, 'Air Support / Maintenance Facility'),
                     (81010, 'Air Traffic Control Center / Command Center'),
                     (81011, 'Boat Ramp / Dock'),
                     (81012, 'Bridge'),
                     (81014, 'Bridge:  Light Rail / Subway'),
                     (81016, 'Bridge:  Railroad'),
                     (81018, 'Bridge:  Road'),
                     (81020, 'Border Crossing / Port of Entry'),
                     (81022, 'Bus Station / Dispatch Facility'),
                     (81024, 'Ferry Terminal / Dispatch Facility'),
                     (81025, 'Harbor / Marina'),
                     (81026, 'Helipad / Heliport / Helispot'),
                     (81028, 'Launch Facility'),
                     (81030, 'Launch Pad'),
                     (81032, 'Light Rail Power Substation'),
                     (81034, 'Light Rail Station'),
                     (81036, 'Park and Ride / Commuter Lot'),
                     (81038, 'Parking Lot Structure / Garage'),
                     (81040, 'Pier / Wharf / Quay / Mole'),
                     (81042, 'Port Facility'),
                     (81044, 'Port Facility: Commercial Port'),
                     (81046, 'Port Facility: Crane'),
                     (81048, 'Port Facility: Maintenance and Fuel Facility'),
                     (81050, 'Port Facility: Modal Transfer Facility'),
                     (81052, 'Port Facility: Passenger Terminal'),
                     (81054, 'Port Facility: Warehouse Storage / Container Yard'),
                     (81056, 'Railroad Facility'),
                     (81058, 'Railroad Command / Control Facility'),
                     (81060, 'Railroad Freight Loading Facility'),
                     (81062, 'Railroad Maintenance / Fuel Facility'),
                     (81064, 'Railroad Roundhouse / Turntable'),
                     (81066, 'Railroad Station'),
                     (81068, 'Railroad Yard'),
                     (81070, 'Rest Stop / Roadside Park'),
                     (81072, 'Seaplane Anchorage / Base'),
                     (81073, 'Snowshed'),
                     (81074, 'Subway Station'),
                     (81076, 'Toll Booth / Plaza'),
                     (81078, 'Truck Stop'),
                     (81080, 'Tunnel'),
                     (81082, 'Tunnel:  Light Rail / Subway'),
                     (81084, 'Tunnel:  Road'),
                     (81086, 'Tunnel:  Railroad'),
                     (81088, 'Weigh Station / Inspection Station')]

    ISLANDMARK_CHOICES = [(1, 'Yes'),
                          (2, 'No'),
                          (0, 'Unknown')]

    POINTLOCATIONTYPE_CHOICES = [(0, 'Unknown'),
                                 (1, 'Centroid'),
                                 (2, 'Egress or Entrance'),
                                 (3, 'Turn-off location'),
                                 (4, 'Approximate')]

    ADMINTYPE_CHOICES = [(0, 'Unknown'),
                         (1, 'Federal'),
                         (2, 'Tribal'),
                         (3, 'State'),
                         (4, 'Regional'),
                         (5, 'County'),
                         (6, 'Municipal'),
                         (7, 'Private')]


    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    objectid = models.IntegerField(unique=True, null=True, blank=True)
    permanent_identifier = models.CharField(max_length=40, null=True, blank=True)
    source_featureid = models.CharField(max_length=40, null=True, blank=True)
    source_datasetid = models.CharField(max_length=40, null=True, blank=True)
    source_datadesc = models.CharField(max_length=100, null=True, blank=True)
    source_originator = models.CharField(max_length=130, null=True, blank=True)
    data_security = models.IntegerField(blank=True, null=True, choices=DATA_SECURITY_CHOICES)
    distribution_policy = models.CharField(max_length=4, choices=DISTRIBUTION_POLICY_CHOICES, null=True, blank=True)
    loaddate = models.DateTimeField(null=True, blank=True)
    ftype = models.CharField(blank=True, null=True, max_length=50)
    fcode = models.IntegerField(blank=True, null=True, choices=FCODE_CHOICES)
    name = models.CharField(max_length=100, null=True, blank=True)
    islandmark = models.IntegerField(null=True, blank=True, choices=ISLANDMARK_CHOICES, verbose_name='Landmark')
    pointlocationtype = models.IntegerField(null=True, blank=True, choices=POINTLOCATIONTYPE_CHOICES,
                                            verbose_name='Point Type')
    admintype = models.IntegerField(null=True, blank=True, choices=ADMINTYPE_CHOICES)
    addressbuildingname = models.CharField(max_length=60, null=True, blank=True, verbose_name='Building Name')
    address = models.CharField(max_length=75, null=True, blank=True)
    city = models.CharField(max_length=40, null=True, blank=True)
    state = models.CharField(max_length=2, null=True, blank=True)
    zipcode = models.CharField(max_length=10, null=True, blank=True)
    gnis_id = models.CharField(max_length=10, null=True, blank=True)
    foot_id = models.CharField(max_length=40, null=True, blank=True)
    complex_id = models.CharField(max_length=40, null=True, blank=True)
    globalid = models.CharField(max_length=38, null=True, blank=True)
    geom = models.PointField()
    objects = models.GeoManager()

    def __unicode__(self):
        return u'{state}, {city}, {name}'.format(name=self.name, state=self.state, city=self.city)

    def full_address(self):
        return u'{address}, {city}, {state}, {zipcode}'.format(address=self.address, city=self.city, state=self.state,
                                                               zipcode=self.zipcode)

    class Meta:
        ordering = ('state', 'city', 'name')


    @classmethod
    def count_differential(cls):
        """
        Reports the count differential between the upstream service and this table.
        """
        url = 'http://services.nationalmap.gov/arcgis/rest/services/govunits/MapServer/{0}/query?' \
              'where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&' \
              'spatialRel=esriSpatialRelIntersects&relationParam=&outFields=&returnGeometry=true' \
              '&maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=false&returnCountOnly=true&orderByFields=' \
              '&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&' \
              'returnDistinctValues=false&f=pjson'

        response = requests.get(url.format(cls.service_id))

        if response.ok:
            response_js = json.loads(response.content)
            upstream_count = response_js.get('count')

            if upstream_count:
                local_count = cls.objects.all().count()
                print 'The upstream service has: {0} features.'.format(upstream_count)
                print 'The local model {1} has: {0} features.'.format(local_count, cls.__name__)
                return local_count - upstream_count
Пример #20
0
class Poi(models.Model):
    """Model representing Point of interest (POI)."""
    name = models.CharField(_(u'name'),
                            max_length=50,
                            help_text=_(u'Name of the POI.'))
    area = models.ForeignKey(Area,
                             help_text=_(u'Area, which POI is situated in.'),
                             verbose_name=_(u'area'))
    type = models.IntegerField(_(u'type'),
                               choices=settings.SNP_POI_TYPES,
                               help_text=_(u'Type of the POI.'))
    active = models.BooleanField(
        _(u'active'),
        default=True,
        help_text=_(u'Boolean of controlling displaying POI in the map.'))
    priority = models.IntegerField(
        _(u'priority'),
        default=5,
        help_text=_(u'Displaying priority of the POI in the map.'))
    note = models.TextField(_(u'note'),
                            blank=True,
                            help_text=_(u'Note about the POI.'))
    photo = models.ManyToManyField(Photo,
                                   blank=True,
                                   null=True,
                                   verbose_name=_(u'list of photos'),
                                   help_text=_(u'Photo of the POI.'))
    jos_article_id = models.ManyToManyField(
        Jos_article_id,
        blank=True,
        null=True,
        verbose_name=_(u'list of articles'),
        help_text=_(
            u'Many-to-many relation with article ids (from Joomla DB).'))
    jos_photo_id = models.ManyToManyField(
        Jos_photo_id,
        blank=True,
        null=True,
        verbose_name=_(u'list of joomla photos'),
        help_text=_(u'Many-to-many relation with photo ids (from Joomla DB).'))
    created_by = models.CharField(
        _(u'author'),
        max_length=50,
        blank=True,
        help_text=_(u'Name of the creator of the POI.'))
    created_at = models.DateTimeField(
        _(u'creation time'),
        default=datetime.now(),
        help_text=_(u'Date-time stamp of creation of the POI.'))

    the_geom = models.PointField(
        _(u'the geom'),
        help_text=_(u'Spatial representation of the POI in the WGS84.'))
    objects = models.GeoManager()

    @property
    def has_photo(self):
        if len(self.photo.all()) == 0 and len(self.jos_photo_id.all()) == 0:
            return False
        else:
            return True

    #has_photo.boolean = True

    @property
    def has_article(self):
        if len(self.jos_article_id.all()) == 0:
            return False
        else:
            return True

    #has_article.boolean = True

    class Meta:
        get_latest_by = 'created_at'
        verbose_name = _(u'Point of interest')
        verbose_name_plural = _(u'Points of interest')

    def __unicode__(self):
        return self.name
Пример #21
0
class TrapLocation(models.Model):
    @classmethod
    def create_from_obj(self, transect_obj, point_obj, the_expedition):
        t = TrapLocation()

        t.expedition = the_expedition

        t.transect_bearing = transect_obj['heading']
        t.team_letter = transect_obj['team_letter']

        t.set_actual_lat_long(point_obj['point'])
        t.set_suggested_lat_long(point_obj['point'])
        t.transect_distance = point_obj['distance']
        t.team_number = point_obj['point_id']

        t.save()

        return t

    def recreate_point_obj(self):
        result = {}
        result['distance'] = self.transect_distance
        result['point_id'] = self.team_number
        result['point'] = [self.suggested_lat(), self.suggested_lon()]
        return result

    """ A location you might decide to set a trap."""
    expedition = models.ForeignKey(Expedition, null=True, blank=True)

    suggested_point = models.PointField(null=True, blank=True)

    actual_point = models.PointField(null=True, blank=True)
    objects = models.GeoManager()

    # instead we're linking directly to the type of trap.
    trap_type = models.ForeignKey(
        TrapType,
        null=True,
        blank=True,
        help_text="Which type of trap, if any, was left at this location.")

    understory = models.TextField(blank=True,
                                  null=True,
                                  default='',
                                  help_text="Understory")

    notes_about_location = models.TextField(
        blank=True, help_text="Notes about the location")

    # this is wrt true north. for wrt mag. north, see method below
    transect_bearing = models.FloatField(blank=True,
                                         null=True,
                                         help_text="Heading of this bearing")
    transect_distance = models.FloatField(
        blank=True, null=True, help_text="Distance along this bearing")

    # Team info:
    team_letter = models.CharField(
        blank=True,
        null=True,
        help_text="Name of team responsible for this location.",
        max_length=256)
    team_number = models.IntegerField(
        blank=True,
        null=True,
        help_text="Differentiates the traps each team is in charge of.")
    order = models.IntegerField(blank=True,
                                null=True,
                                help_text="Order in which to show this trap.")

    habitat = models.ForeignKey(
        Habitat,
        null=True,
        blank=True,
        help_text="What habitat best describes this location?",
        on_delete=models.SET_NULL)

    # info about the outcome:
    whether_a_trap_was_set_here = models.BooleanField(
        default=False,
        help_text='''We typically won't use all the locations suggested by the
        randomization recipe; this denotes that a trap was actually placed at
        or near this point.''')
    bait = models.ForeignKey(Bait,
                             null=True,
                             blank=True,
                             help_text="Any bait used",
                             on_delete=models.SET_NULL)
    animal = models.ForeignKey(Animal,
                               null=True,
                               blank=True,
                               help_text="Any animals caught",
                               on_delete=models.SET_NULL)
    bait_still_there = models.BooleanField(
        default=False,
        help_text='''Was the bait you left in the trap still there
        when you came back?''')

    notes_about_outcome = models.TextField(
        blank=True, help_text="Any miscellaneous notes about the outcome")

    student_names = models.TextField(
        blank=True,
        null=True,
        help_text='''Names of the students responsible for this location
        (this would be filled in, if at all, by the instructor after the
        students have left the forest.''',
        max_length=256)

    def date(self):
        if self.expedition and self.expedition.end_date_of_expedition:
            return self.expedition.end_date_of_expedition.strftime("%m/%d/%y")
        else:
            return None

    def date_for_solr(self):
        if self.expedition:
            return self.expedition.end_date_of_expedition
        else:
            return None

    def trap_nickname(self):
        return "%s%d" % (self.team_letter, self.team_number)

    def transect_endpoints(self):
        trig_radians_angle = positive_radians(
            degrees_to_radians(self.transect_bearing))
        side_of_square = 250.0  # meters. #TODO move this to settings.
        transect_length = length_of_transect(trig_radians_angle,
                                             side_of_square)
        square_center = self.expedition.grid_square.center
        center_point = [square_center.lat(), square_center.lon()]
        result = {}
        result['center'] = [square_center.lat(), square_center.lon()]
        result['edge'] = list(
            walk_transect(center_point, transect_length, trig_radians_angle))
        return result

    def set_transect_bearing_wrt_magnetic_north(self, mnb):
        result = mnb + 13.0
        if result < 0:
            result = result + 360.0
        if result > 360.0:
            result = result - 360.0

        self.transect_bearing = result

    def set_suggested_lat_lon_from_mag_north(self,
                                             heading_degrees_from_mag_north,
                                             distance):
        self.set_transect_bearing_wrt_magnetic_north(
            heading_degrees_from_mag_north)
        trig_radians_angle = positive_radians(
            degrees_to_radians(self.transect_bearing))
        square_center = self.expedition.grid_square.center
        center_point = [square_center.lat(), square_center.lon()]
        suggested_location = list(
            walk_transect(center_point, distance, trig_radians_angle))
        self.set_suggested_lat_long(suggested_location)

    def transect_bearing_wrt_magnetic_north(self):
        result = self.transect_bearing - 13.0
        if result < 0:
            result = result + 360.0
        return result

    def set_suggested_lat_long(self, coords):
        # see
        # https://code.djangoproject.com/attachment/ticket/
        #     16778/postgis-adapter-2.patch
        # if this breaks again.
        self.suggested_point = "POINT(%s %s)" % (coords[0], coords[1])

    def set_actual_lat_long(self, coords):
        # see
        # https://code.djangoproject.com/attachment/ticket/
        #     16778/postgis-adapter-2.patch
        # if this breaks again.
        self.actual_point = "POINT(%s %s)" % (coords[0], coords[1])

    def __unicode__(self):
        return self.gps_coords()

    def suggested_gps_coords(self):
        return "%s, %s" % (self.suggested_NSlat(), self.suggested_EWlon())

    def actual_gps_coords(self):
        return "%s, %s" % (self.actual_NSlat(), self.actual_EWlon())

    def suggested_NSlat(self):
        lat = self.suggested_lat()
        if lat:
            if lat > 0:
                return '%0.5F N' % abs(lat)
            return '%0.5F S' % abs(lat)
        return None

    def suggested_EWlon(self):
        lon = self.suggested_lon()
        if lon:
            if lon < 0:
                return '%0.5F W' % abs(lon)
            return '%0.5F E' % abs(lon)
        return None

    def actual_NSlat(self):
        lat = self.actual_lat()
        if lat:
            if lat > 0:
                return '%0.5F N' % abs(lat)
            return '%0.5F S' % abs(lat)
        return None

    def actual_EWlon(self):
        lon = self.actual_lon()
        if lon:
            if lon < 0:
                return '%0.5F W' % abs(lon)
            return '%0.5F E' % abs(lon)
        return None

    def suggested_lat(self):
        if self.suggested_point:
            return self.suggested_point.coords[0]
        return None

    def suggested_lon(self):
        if self.suggested_point:
            return self.suggested_point.coords[1]
        return None

    def actual_lat(self):
        if self.actual_point:
            return self.actual_point.coords[0]
        return None

    def actual_lon(self):
        if self.actual_point:
            return self.actual_point.coords[1]
        return None

    def species_if_any(self):
        if self.animal:
            return self.animal.species.common_name
        else:
            return None

    def habitat_if_any(self):
        if self.habitat:
            return self.habitat.label
        else:
            return None

    def habitat_id_if_any(self):
        if self.habitat:
            return self.habitat.id
        else:
            return None

    def school_if_any(self):
        if self.expedition.school:
            return self.expedition.school.name
        else:
            return None

    def search_map_repr(self):
        result = {}

        info_string = \
            "Animal: %s</br>Habitat: %s</br>School: %s</br>Date: %s" % (
                self.species_if_any(), self.habitat_if_any(),
                self.school_if_any(), self.date())

        result['name'] = info_string
        result['where'] = [self.actual_lat(), self.actual_lon()]

        result['species'] = self.species_if_any()
        result['habitat_id'] = self.habitat_id_if_any()
        result['habitat'] = self.habitat_if_any()
        result['school'] = self.school_if_any()
        result['date'] = self.date()

        return result

    def dir(self):
        return dir(self)

    def gps_coords(self):
        return "%s, %s" % (self.actual_NSlat(), self.actual_EWlon())
Пример #22
0
class Project(models.Model):
    pjid = models.AutoField(primary_key=True)
    Locatie = models.CharField(max_length=255, blank=False)
    Hoofdtype = models.ForeignKey(HoofdType,
                                  related_name='hoofd_type_project',
                                  on_delete=models.CASCADE,
                                  blank=True,
                                  null=True)
    Aard = models.ManyToManyField(ProjectType,
                                  related_name='project_type_project')
    Intakedatum = models.DateField(blank=False, default=datetime.now)

    startdatum = models.DateField(blank=False, default=datetime.now)
    einddatum = models.DateField(blank=False, default=datetime.now)

    Plangebied = models.PolygonField(srid=4326, null=True)

    Organisatie_opdrachtgever = models.ForeignKey(
        Organisatie,
        blank=True,
        related_name='organisatie_project',
        on_delete=models.CASCADE,
        null=True)

    Bestuurlijk_opdrachtgever = models.ForeignKey(
        Employee,
        related_name='administrativeclient_project',
        on_delete=models.CASCADE,
        blank=True,
        null=True)
    Ambtelijk_opdrachtgever = models.ForeignKey(
        Employee,
        blank=True,
        related_name='officialclient_project',
        on_delete=models.CASCADE,
        null=True)
    Opdracht_verantwoordelijke = models.ForeignKey(
        Employee,
        blank=False,
        related_name='maincontractor_project',
        on_delete=models.CASCADE,
        null=True)
    Deel_projectleider = models.ForeignKey(
        Employee,
        blank=True,
        related_name='subcontractor_project',
        on_delete=models.CASCADE,
        null=True)
    Account_houder = models.ForeignKey(Employee,
                                       blank=True,
                                       related_name='accountant_project',
                                       on_delete=models.CASCADE,
                                       null=True)

    Timetellnummer = models.CharField(max_length=18, blank=True, null=True)

    # Convert manytomany list into a string
    @property
    def Type(self):
        return '{}'.format(self.Hoofdtype)

    @property
    def AardList(self):
        return ', '.join([a.Soort for a in self.Aard.all()])

    @property
    def Jaar(self):
        return '{}'.format(self.startdatum.year)

    def __str__(self):
        return '{} - {} - {} - {}'.format(self.pjid, self.Type, self.AardList,
                                          self.Locatie, self.Jaar)

    objects = models.GeoManager()

    Indicatiebedrag = models.DecimalField(max_digits=9,
                                          decimal_places=2,
                                          blank=True,
                                          default=0.00)
    Maximumbedrag = models.DecimalField(max_digits=9,
                                        decimal_places=2,
                                        blank=True,
                                        default=0.00)
    Vervolgafspraken = models.TextField(max_length=None, blank=True, null=True)

    class Meta:
        db_table = 'project'
Пример #23
0
class Instance(models.Model):
    json = JSONField(default={}, null=False)
    xml = models.TextField()
    user = models.ForeignKey(User, related_name='instances', null=True)
    xform = models.ForeignKey(XForm, null=True, related_name='instances')
    survey_type = models.ForeignKey(SurveyType)

    # shows when we first received this instance
    date_created = models.DateTimeField(auto_now_add=True)

    # this will end up representing "date last parsed"
    date_modified = models.DateTimeField(auto_now=True)

    # this will end up representing "date instance was deleted"
    deleted_at = models.DateTimeField(null=True, default=None)

    # ODK keeps track of three statuses for an instance:
    # incomplete, submitted, complete
    # we add a fourth status: submitted_via_web
    status = models.CharField(max_length=20,
                              default=u'submitted_via_web')
    uuid = models.CharField(max_length=249, default=u'')
    version = models.CharField(max_length=XFORM_TITLE_LENGTH, null=True)

    # store an geographic objects associated with this instance
    geom = models.GeometryCollectionField(null=True)
    objects = models.GeoManager()

    tags = TaggableManager()

    class Meta:
        app_label = 'logger'

    @classmethod
    def set_deleted_at(cls, instance_id, deleted_at=timezone.now()):
        try:
            instance = cls.objects.get(id=instance_id)
        except cls.DoesNotExist:
            pass
        else:
            instance.set_deleted(deleted_at)

    def _check_active(self, force):
        """Check that form is active and raise exception if not.

        :param force: Ignore restrictions on saving.
        """
        if not force and self.xform and not self.xform.downloadable:
            raise FormInactiveError()

    def _set_geom(self):
        xform = self.xform
        data_dictionary = xform.data_dictionary()
        geo_xpaths = data_dictionary.geopoint_xpaths()
        doc = self.get_dict()
        points = []

        if len(geo_xpaths):
            for xpath in geo_xpaths:
                geometry = [float(s) for s in doc.get(xpath, u'').split()]

                if len(geometry):
                    lat, lng = geometry[0:2]
                    points.append(Point(lng, lat))

            if not xform.instances_with_geopoints and len(points):
                xform.instances_with_geopoints = True
                xform.save()

            self.geom = GeometryCollection(points)

    def _set_json(self):
        doc = self.get_dict()

        if not self.date_created:
            now = submission_time()
            self.date_created = now

        point = self.point
        if point:
            doc[GEOLOCATION] = [point.y, point.x]

        doc[SUBMISSION_TIME] = self.date_created.strftime(MONGO_STRFTIME)
        doc[XFORM_ID_STRING] = self._parser.get_xform_id_string()
        doc[SUBMITTED_BY] = self.user.username\
            if self.user is not None else None
        self.json = doc

    def _set_parser(self):
        if not hasattr(self, "_parser"):
            self._parser = XFormInstanceParser(
                self.xml, self.xform.data_dictionary())

    def _set_survey_type(self):
        self.survey_type, created = \
            SurveyType.objects.get_or_create(slug=self.get_root_node_name())

    def _set_uuid(self):
        if self.xml and not self.uuid:
            uuid = get_uuid_from_xml(self.xml)
            if uuid is not None:
                self.uuid = uuid
        set_uuid(self)

    def get(self, abbreviated_xpath):
        self._set_parser()
        return self._parser.get(abbreviated_xpath)

    def get_dict(self, force_new=False, flat=True):
        """Return a python object representation of this instance's XML."""
        self._set_parser()

        return self._parser.get_flat_dict_with_attributes() if flat else\
            self._parser.to_dict()

    def get_full_dict(self):
        # TODO should we store all of these in the JSON no matter what?
        d = self.json
        data = {
            UUID: self.uuid,
            ID: self.id,
            BAMBOO_DATASET_ID: self.xform.bamboo_dataset,
            self.USERFORM_ID: u'%s_%s' % (
                self.user.username,
                self.xform.id_string),
            ATTACHMENTS: [a.media_file.name for a in
                          self.attachments.all()],
            self.STATUS: self.status,
            TAGS: list(self.tags.names()),
            NOTES: self.get_notes(),
            VERSION: self.version
        }

        if isinstance(self.instance.deleted_at, datetime):
            data[DELETEDAT] = self.deleted_at.strftime(MONGO_STRFTIME)

        d.update(data)

        return d

    def get_notes(self):
        return [note['note'] for note in self.notes.values('note')]

    def get_root_node(self):
        self._set_parser()
        return self._parser.get_root_node()

    def get_root_node_name(self):
        self._set_parser()
        return self._parser.get_root_node_name()

    @property
    def point(self):
        gc = self.geom

        if gc and len(gc):
            return gc[0]

    def save(self, *args, **kwargs):
        force = kwargs.get('force')

        if force:
            del kwargs['force']

        self._check_active(force)

        self._set_geom()
        self._set_json()
        self._set_survey_type()
        self._set_uuid()
        self.version = self.xform.version
        super(Instance, self).save(*args, **kwargs)

    def set_deleted(self, deleted_at=timezone.now()):
        self.deleted_at = deleted_at
        self.save()
        # force submission count re-calculation
        self.xform.submission_count(force_update=True)
        self.parsed_instance.save()
Пример #24
0
class StarModel(models.Model):
    """
    Additional data and simulated info about stars.
    Data needs to be generated using 'build_model' before being accessed
    """

    star = models.OneToOneField(Star,
                                db_index=True,
                                help_text="The star with real data",
                                default=1)
    star_type = models.ForeignKey(StarType,
                                  help_text="Stellar Classification",
                                  blank=True,
                                  null=True)
    luminosity_class = models.ForeignKey(StarLuminosityType,
                                         help_text="Luminosity Class (0-VII)",
                                         blank=True,
                                         null=True)
    luminosity_mod = models.CharField(
        max_length=5,
        help_text="Luminosity sub class (a, ab, b, a-0",
        blank=True,
        null=True)
    base_color = models.CharField(max_length=8,
                                  help_text="Basic RBG Color",
                                  default="#ffddbe",
                                  blank=True,
                                  null=True)

    rand_seed = models.FloatField(
        help_text="Random Seed from 0-1 used to build notional system",
        blank=True,
        null=True,
        default=0)
    guessed_temp = models.FloatField(help_text="Guessed at Temperature",
                                     blank=True,
                                     null=True,
                                     default=0)
    guessed_mass = models.FloatField(help_text="Guessed at Mass",
                                     blank=True,
                                     null=True,
                                     default=0)
    guessed_radius = models.FloatField(help_text="Guessed at Radius",
                                       blank=True,
                                       null=True,
                                       default=0)
    guessed_age = models.FloatField(help_text="Guessed at Age",
                                    blank=True,
                                    null=True,
                                    default=0)

    json_of_closest_stars = models.TextField(
        help_text=
        "List of Stars, will be filled in automatically on first calculation",
        blank=True,
        null=True)

    ids_of_companion_stars = models.CharField(
        max_length=30,
        help_text="Comma-separated IDs of any stars within .3 LY",
        blank=True,
        null=True)

    location = models.PointField(db_index=True,
                                 dim=3,
                                 blank=True,
                                 null=True,
                                 srid=900913)
    objects = models.GeoManager()

    def build_model(self, star_id=None, star_prime=None, forced=False):
        np.random.seed()

        self.add_rand_seed(forced)

        if not star_prime and not star_id:
            star_prime = self.star

        if star_prime:
            self.star = star_prime
        else:
            self.star = Star.objects.get(id=star_id)
        if self.star:
            star_a, star_b, star_c, star_d = get_star_type(self.star.spectrum)
            self.add_type(star_a)
            self.add_color(star_a, star_b, star_c)
            self.add_luminosity(star_c)
            self.luminosity_mod = star_d

        self.add_rand_variables(forced)

        self.save()

    def add_rand_seed(self, forced=False):
        add_it = True
        if not forced and self.rand_seed:
            add_it = False
        if add_it:
            self.rand_seed = np.random.random()  #rand_range(0, 1)
            self.save()

    def add_rand_variables(self, forced=False):
        add_it = True
        if not forced and self.guessed_temp:
            add_it = False
        if add_it:
            options = {
                'rand_seed': self.rand_seed,
                'star_type': self.star_type,
                'temp': 0,
                'mass': 0,
                'age': 0,
                'radius': 0,
                'luminosity_class': self.luminosity_class,
                'luminosity_mod': self.luminosity_mod
            }

            settings = star_variables(options)

            self.guessed_temp = settings.get('temp', 0)
            self.guessed_mass = settings.get('mass', 0)
            self.guessed_radius = settings.get('radius', 0)
            self.guessed_age = settings.get('age', 0)
            self.save()

    def add_luminosity(self, star_c):
        result = "ok"
        try:
            star_type = StarLuminosityType.objects.get(symbol=star_c)
            self.luminosity_class = star_type
        except StarLuminosityType.DoesNotExist:
            result = "unknown"
        return result

    def add_type(self, star_a):
        result = "ok"
        try:
            star_type = StarType.objects.get(symbol=star_a)
            self.star_type = star_type
        except StarType.DoesNotExist:
            result = "unknown"
        return result

    def add_color(self, star_a="K", star_b="", star_c=""):
        star = self
        found_color = ""
        if star_a or star_b or star_c:
            found_color = color_of_star(star_a, star_b, star_c)
        if not found_color and star.star and star.star.spectrum:
            star_a, star_b, star_c = get_star_type(star.star.spectrum)
            found_color = color_of_star(star_a, star_b, star_c)
        if not found_color:
            if star.star_type and star.star_type.base_color:
                found_color = star.star_type.base_color
        star.base_color = found_color
        star.save()

    class Meta:
        verbose_name_plural = 'Stars (Simulated)'
        ordering = ['star']

    def nearby_stars(self, force_regenerate=False):
        if self.json_of_closest_stars and not force_regenerate:
            star_list = json.loads(self.json_of_closest_stars)
        else:
            star_list = closest_stars(self, StarModel)
            self.json_of_closest_stars = json.dumps(star_list)
            self.save()

        return star_list

    def nearby_stars_json(self):
        self.nearby_stars()
        return self.json_of_closest_stars

    def nearby_stars_json_force_recalc(self):
        self.nearby_stars(force_regenerate=True)
        return self.json_of_closest_stars

    additional_methods = [
        'nearby_stars',
    ]

    def get_params(self, requested_methods=None, only_variables=None):
        """
        Converts parameters to object.

        Options:
            requested_methods = ['__unicode__', ] (to also call these functions and return results)
            only_variables = ['name', 'title', ] (to only return values of these model variables)

        """
        additional_methods = self.additional_methods

        if requested_methods:
            additional_methods = requested_methods + additional_methods
        dumps = dict()

        if not only_variables:
            model_fields = [field.name for field in self._meta.fields]
        else:
            model_fields = only_variables

        for field in model_fields:
            val = self.__getattribute__(field)
            if type(val) == Point:
                point = dict()
                point['x'] = val.x
                point['y'] = val.y
                point['z'] = val.z
                dumps[str(field)] = point
            else:
                dumps[str(field)] = str(val)
        for func in additional_methods:
            dumps[func] = getattr(self, func)()
        return dumps
Пример #25
0
class Person(UserenaBaseProfile):
    # define the fields for your item here like:
    name = models.CharField(max_length=100, null=True, blank=True)
    mid = models.CharField(max_length=100, null=True, blank=True)
    page_url = models.URLField(null=True, blank=True)
    preferred_email = models.EmailField(null=True, blank=True)
    company_name = models.CharField(max_length=100, null=True, blank=True)
    city = models.CharField(max_length=100, null=True, blank=True)
    state = models.CharField(max_length=100, null=True, blank=True)
    country = models.CharField(max_length=100, null=True, blank=True)

    #wesleyan education
    wesleyan_degree_school_1 = models.CharField(max_length=100,
                                                null=True,
                                                blank=True)
    wesleyan_degree_year_1 = models.CharField(max_length=100,
                                              null=True,
                                              blank=True)
    wesleyan_degree_1 = models.CharField(max_length=100, null=True, blank=True)
    wesleyan_degree_1_major_1 = models.CharField(max_length=100,
                                                 null=True,
                                                 blank=True)
    wesleyan_degree_1_major_2 = models.CharField(max_length=100,
                                                 null=True,
                                                 blank=True)
    wesleyan_degree_1_major_3 = models.CharField(max_length=100, null=True)

    # member information
    first_name = models.CharField(max_length=100, null=True, blank=True)
    last_name = models.CharField(max_length=100, null=True, blank=True)
    nickname = models.CharField(max_length=100, null=True, blank=True)
    last_name_at_grad = models.CharField(max_length=100, null=True, blank=True)
    preferred_class_year = models.CharField(max_length=100,
                                            null=True,
                                            blank=True)
    preferred_email = models.CharField(max_length=100, null=True, blank=True)

    #primary employment
    company_name = models.CharField(max_length=100, null=True, blank=True)
    position_title = models.CharField(max_length=100, null=True, blank=True)
    position_status = models.CharField(max_length=100, null=True, blank=True)

    business_address_1 = models.CharField(max_length=100,
                                          null=True,
                                          blank=True)
    business_address_2 = models.CharField(max_length=100,
                                          null=True,
                                          blank=True)
    business_address_city = models.CharField(max_length=100,
                                             null=True,
                                             blank=True)
    business_address_state = models.CharField(max_length=100,
                                              null=True,
                                              blank=True)
    business_address_zip = models.CharField(max_length=100,
                                            null=True,
                                            blank=True)
    business_address_country = models.CharField(max_length=100,
                                                null=True,
                                                blank=True)
    occupation = models.CharField(max_length=100, null=True, blank=True)
    industry = models.CharField(max_length=100, null=True, blank=True)

    #geolocation
    location = models.PointField(null=True, blank=True)

    # Override the default manager with GeoManager instance
    objects = models.GeoManager()

    people = models.Manager()
    geolocated = PersonLocationManager()
    names = PersonNameManager()

    user = models.OneToOneField(User,
                                null=True,
                                blank=True,
                                unique=True,
                                verbose_name=_('user'))

    #sites = models.ManyToManyField(Site)

    def makeName(self):
        n = self.name.split(',')
        self.first_name = n[1]
        self.last_name = n[0]

    def __unicode__(self):
        if self.first_name and self.last_name:
            return self.last_name + ", " + self.first_name
        elif self.name:
            self.makeName()
            return self.last_name + ', ' + self.first_name
        else:
            return u"Person object pk=%s" % self.pk
Пример #26
0
class InstanceHistory(models.Model, InstanceBaseClass):

    class Meta:
        app_label = 'logger'

    xform_instance = models.ForeignKey(
        Instance, related_name='submission_history')
    user = models.ForeignKey(User, null=True)

    xml = models.TextField()
    # old instance id
    uuid = models.CharField(max_length=249, default=u'')

    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    submission_date = models.DateTimeField(null=True, default=None)
    geom = models.GeometryCollectionField(null=True)
    objects = models.GeoManager()

    @property
    def xform(self):
        return self.xform_instance.xform

    @property
    def attachments(self):
        return self.xform_instance.attachments.all()

    @property
    def json(self):
        return self.get_full_dict(load_existing=False)

    @property
    def status(self):
        return self.xform_instance.status

    @property
    def tags(self):
        return self.xform_instance.tags

    @property
    def notes(self):
        return self.xform_instance.notes.all()

    @property
    def version(self):
        return self.xform_instance.version

    @property
    def osm_data(self):
        return self.xform_instance.osm_data

    @property
    def deleted_at(self):
        return None

    def _set_parser(self):
        if not hasattr(self, "_parser"):
            self._parser = XFormInstanceParser(
                self.xml, self.xform_instance.xform
            )

    @classmethod
    def set_deleted_at(cls, instance_id, deleted_at=timezone.now()):
        return None
Пример #27
0
class BasicData(models.Model):
    school_code = models.BigIntegerField(primary_key=True)
    centroid = models.GeometryField(blank=True, null=True)
    district = models.CharField(max_length=50, blank=True)
    school_name = models.CharField(max_length=200, blank=True)
    block_name = models.CharField(max_length=50, blank=True)
    cluster_name = models.CharField(max_length=50, blank=True)
    village_name = models.CharField(max_length=50, blank=True)
    assembly_name = models.CharField(max_length=35, blank=True)
    parliament_name = models.CharField(max_length=35, blank=True)
    pincode = models.IntegerField(null=True, blank=True)
    new_pincode = models.IntegerField(null=True, blank=True)
    rural_urban = models.IntegerField(choices=AREA, null=True, blank=True)
    medium_of_instruction = models.IntegerField(choices=MEDIUM, null=True, blank=True)
    distance_brc = models.FloatField(null=True, blank=True)
    distance_crc = models.FloatField(null=True, blank=True)
    yeur_estd = models.IntegerField(null=True, blank=True)
    pre_pry_yn = models.IntegerField(null=True, blank=True)
    residential_sch_yn = models.IntegerField(null=True, blank=True)
    sch_management = models.IntegerField(choices=SCHOOL_MANAGEMENT, null=True, blank=True)
    lowest_class = models.IntegerField(null=True, blank=True)
    highest_class = models.IntegerField(null=True, blank=True)
    sch_category = models.IntegerField(choices=SCHOOL_CATEGORY, null=True, blank=True)
    pre_pry_students = models.IntegerField(null=True, blank=True)
    school_type = models.IntegerField(choices=SCHOOL_TYPES, null=True, blank=True)
    shift_school_yn = models.IntegerField(null=True, blank=True)
    no_of_working_days = models.IntegerField(null=True, blank=True)
    no_of_acad_inspection = models.IntegerField(null=True, blank=True)
    residential_sch_type = models.IntegerField(null=True, blank=True)
    pre_pry_teachers = models.IntegerField(null=True, blank=True)
    visits_by_brc = models.IntegerField(null=True, blank=True)
    visits_by_crc = models.IntegerField(null=True, blank=True)
    school_dev_grant_recd = models.FloatField(null=True, blank=True)
    school_dev_grant_expnd = models.FloatField(null=True, blank=True)
    tlm_grant_recd = models.FloatField(null=True, blank=True)
    tlm_grant_expnd = models.FloatField(null=True, blank=True)
    funds_from_students_recd = models.FloatField(null=True, blank=True)
    funds_from_students_expnd = models.FloatField(null=True, blank=True)
    building_status = models.IntegerField(choices=BUILDING_STATUS, null=True, blank=True)
    tot_clrooms = models.IntegerField(null=True, blank=True)
    classrooms_in_good_condition = models.IntegerField(null=True, blank=True)
    classrooms_require_major_repair = models.IntegerField(choices=YESNO, null=True, blank=True)
    classrooms_require_minor_repair = models.IntegerField(choices=YESNO, null=True, blank=True)
    other_rooms_in_good_cond = models.IntegerField(null=True, blank=True)
    other_rooms_need_major_rep = models.IntegerField(null=True, blank=True)
    other_rooms_need_minor_rep = models.IntegerField(null=True, blank=True)
    toilet_common = models.IntegerField(null=True, blank=True)
    toilet_boys = models.IntegerField(null=True, blank=True)
    toilet_girls = models.IntegerField(null=True, blank=True)
    kitchen_devices_grant = models.IntegerField(null=True, blank=True)
    status_of_mdm = models.IntegerField(choices=MDM_STATUS, null=True, blank=True)
    computer_aided_learnin_lab = models.IntegerField(choices=YESNO, null=True, blank=True)
    separate_room_for_headmaster = models.IntegerField(choices=YESNO, null=True, blank=True)
    electricity = models.IntegerField(choices=YESNO, null=True, blank=True)
    boundary_wall = models.IntegerField(choices=BOUNDARY_WALL, null=True, blank=True)
    library_yn = models.IntegerField(choices=YESNO, null=True, blank=True)
    playground = models.IntegerField(choices=YESNO, null=True, blank=True)
    blackboard = models.IntegerField(null=True, blank=True)
    books_in_library = models.IntegerField(null=True, blank=True)
    drinking_water = models.IntegerField(choices=DRINKING_WATER, null=True, blank=True)
    medical_checkup = models.IntegerField(choices=YESNO, null=True, blank=True)
    ramps = models.IntegerField(choices=YESNO, null=True, blank=True)
    no_of_computers = models.IntegerField(null=True, blank=True)
    male_tch = models.IntegerField(null=True, blank=True)
    female_tch = models.IntegerField(null=True, blank=True)
    noresp_tch = models.IntegerField(null=True, blank=True)
    head_teacher = models.IntegerField(null=True, blank=True)
    graduate_teachers = models.IntegerField(null=True, blank=True)
    tch_with_professional_qualification = models.IntegerField(null=True, blank=True)
    days_involved_in_non_tch_assgn = models.IntegerField(null=True, blank=True)
    teachers_involved_in_non_tch_assgn = models.IntegerField(null=True, blank=True)
    class1_total_enr_boys = models.IntegerField(blank=True, null=True)
    class2_total_enr_boys = models.IntegerField(blank=True, null=True)
    class3_total_enr_boys = models.IntegerField(blank=True, null=True)
    class4_total_enr_boys = models.IntegerField(blank=True, null=True)
    class5_total_enr_boys = models.IntegerField(blank=True, null=True)
    class6_total_enr_boys = models.IntegerField(blank=True, null=True)
    class7_total_enr_boys = models.IntegerField(blank=True, null=True)
    class8_total_enr_boys = models.IntegerField(blank=True, null=True)
    class1_total_enr_girls = models.IntegerField(blank=True, null=True)
    class2_total_enr_girls = models.IntegerField(blank=True, null=True)
    class3_total_enr_girls = models.IntegerField(blank=True, null=True)
    class4_total_enr_girls = models.IntegerField(blank=True, null=True)
    class5_total_enr_girls = models.IntegerField(blank=True, null=True)
    class6_total_enr_girls = models.IntegerField(blank=True, null=True)
    class7_total_enr_girls = models.IntegerField(blank=True, null=True)
    class8_total_enr_girls = models.IntegerField(blank=True, null=True)
    total_boys = models.IntegerField(blank=True, null=True)
    total_girls = models.IntegerField(blank=True, null=True)

    objects = models.GeoManager()

    class Meta:
        abstract = True

    def __unicode__(self):
        return self.school_name

    @property
    def popup_content(self):
        return self.school_name
Пример #28
0
class Instance(models.Model):
    """
    Each "Tree Map" is a single instance
    """
    name = models.CharField(max_length=255, unique=True)

    url_name = models.CharField(
        max_length=255,
        unique=True,
        validators=[
            reserved_name_validator,
            RegexValidator(
                r'^%s$' % URL_NAME_PATTERN,
                trans('Must start with a letter and may only contain '
                      'letters, numbers, or dashes ("-")'),
                trans('Invalid URL name'))
        ])
    """
    Basemap type     Basemap data
    ------------     -----------------
    Google           Google_API_Key
    Bing             Bing_API_Key
    TMS              TMS URL with {x},{y},{z}
    """
    basemap_type = models.CharField(max_length=255,
                                    choices=(("google", "Google"), ("bing",
                                                                    "Bing"),
                                             ("tms", "Tile Map Service")),
                                    default="google")
    basemap_data = models.CharField(max_length=255, null=True, blank=True)
    """
    The current database revision for the instance

    This revision is used to determine if tiles should be cached.
    In particular, the revision has *no* effect on the actual
    data.

    Generally we make tile requests like:
    http://tileserver/tile/{layer}/{rev}/{Z}/{Y}/{X}

    There is a database trigger that updates the
    revision whenever an edit to a geometry field is made
    so you don't have to worry about it.

    You should *not* edit this field.
    """
    geo_rev = models.IntegerField(default=1)

    eco_benefits_conversion = models.ForeignKey('BenefitCurrencyConversion',
                                                null=True,
                                                blank=True)
    """ Center of the map when loading the instance """
    bounds = models.MultiPolygonField(srid=3857)
    """
    Override the center location (which is, by default,
    the centroid of "bounds"
    """
    center_override = models.PointField(srid=3857, null=True, blank=True)

    default_role = models.ForeignKey('Role', related_name='default_role')

    users = models.ManyToManyField('User',
                                   through='InstanceUser',
                                   null=True,
                                   blank=True)

    boundaries = models.ManyToManyField('Boundary', null=True, blank=True)
    """
    Config contains a bunch of config variables for a given instance
    these can be accessed via per-config properties such as
    `advanced_search_fields`. Note that it is a DotDict, and so supports
    get() with a dotted key and a default, e.g.
        instance.config.get('fruit.apple.type', 'delicious')
    as well as creating dotted keys when no keys in the path exist yet, e.g.
        instance.config = DotDict({})
        instance.config.fruit.apple.type = 'macoun'
    """
    config = JSONField(blank=True)

    is_public = models.BooleanField(default=False)

    logo = models.ImageField(upload_to='logos', null=True, blank=True)

    itree_region_default = models.CharField(max_length=20,
                                            null=True,
                                            blank=True,
                                            choices=ITREE_REGION_CHOICES)

    # Monotonically increasing number used to invalidate my InstanceAdjuncts
    adjuncts_timestamp = models.BigIntegerField(default=0)

    objects = models.GeoManager()

    def __unicode__(self):
        return self.name

    def _make_config_property(prop, default=None):
        def get_config(self):
            return self.config.get(prop, default)

        def set_config(self, value):
            self.config[prop] = value

        return property(get_config, set_config)

    date_format = _make_config_property('date_format', settings.DATE_FORMAT)

    short_date_format = _make_config_property('short_date_format',
                                              settings.SHORT_DATE_FORMAT)

    scss_variables = _make_config_property('scss_variables')

    map_feature_types = _make_config_property('map_feature_types', ['Plot'])

    mobile_search_fields = _make_config_property('mobile_search_fields',
                                                 DEFAULT_MOBILE_SEARCH_FIELDS)

    mobile_api_fields = _make_config_property('mobile_api_fields',
                                              DEFAULT_MOBILE_API_FIELDS)

    non_admins_can_export = models.BooleanField(default=True)

    @property
    def advanced_search_fields(self):
        # TODO pull from the config once users have a way to set search fields

        if not self.feature_enabled('advanced_search_filters'):
            return {
                'standard': [],
                'missing': [],
                'display': [],
                'udfc': self._get_udfc_search_fields()
            }

        from treemap.models import MapFeature  # prevent circular import

        fields = {
            'standard': [{
                'identifier': 'tree.diameter',
                'search_type': 'RANGE'
            }, {
                'identifier': 'tree.date_planted',
                'search_type': 'RANGE'
            }, {
                'identifier': 'mapFeature.updated_at',
                'search_type': 'RANGE'
            }],
            'display': [{
                'model': 'Tree',
                'label': 'Show trees'
            }, {
                'model': 'EmptyPlot',
                'label': 'Show empty planting sites'
            }],
            'missing': [{
                'identifier': 'species.id',
                'label': 'Show missing species',
                'search_type': 'ISNULL',
                'value': 'true'
            }, {
                'identifier': 'tree.diameter',
                'label': 'Show missing trunk diameter',
                'search_type': 'ISNULL',
                'value': 'true'
            }, {
                'identifier': 'mapFeaturePhoto.id',
                'label': 'Show missing photos',
                'search_type': 'ISNULL',
                'value': 'true'
            }],
        }

        def make_display_filter(feature_name):
            Feature = MapFeature.get_subclass(feature_name)
            if hasattr(Feature, 'display_name_plural'):
                plural = Feature.display_name_plural
            else:
                plural = Feature.display_name + 's'
            return {'label': 'Show %s' % plural.lower(), 'model': feature_name}

        fields['display'] += [
            make_display_filter(feature_name)
            for feature_name in self.map_feature_types
            if feature_name != 'Plot'
        ]

        # It makes styling easier if every field has an identifier
        num = 0
        for filters in fields.itervalues():
            for field in filters:
                field['id'] = "%s_%s" % (field.get('identifier', ''), num)
                num += 1

        fields['udfc'] = self._get_udfc_search_fields()

        return fields

    def _get_udfc_search_fields(self):
        from treemap.util import to_object_name

        empty_udfc = {
            to_object_name(n_k): {
                to_object_name(m_k): {
                    'fields': [],
                    'udfd': None
                }
                for m_k in UDFC_MODELS
            }
            for n_k in UDFC_NAMES
        }

        udfds = []
        for model_name in UDFC_MODELS:
            for udfd in udf_defs(self, model_name):
                if udfd.name in UDFC_NAMES:
                    udfds.append(udfd)

        udfc = deepcopy(empty_udfc)

        for udfd in udfds:
            udfd_info = {
                'udfd': udfd,
                'fields': udfd.datatype_dict[0]['choices']
            }
            name_dict = udfc[to_object_name(udfd.name)]
            name_dict[to_object_name(udfd.model_type)] = udfd_info

        return udfc

    @property
    def supports_resources(self):
        """
        Determine whether this instance has multiple map feature
        types (plots + "resources") or not.
        """
        n = len(self.map_feature_types)
        return n > 1

    @property
    def extent_as_json(self):
        boundary = self.bounds.boundary
        xmin, ymin, xmax, ymax = boundary.extent

        return json.dumps({
            'xmin': xmin,
            'ymin': ymin,
            'xmax': xmax,
            'ymax': ymax
        })

    @property
    def bounds_as_geojson(self):
        boundary = self.bounds
        boundary.transform(4326)
        return boundary.json

    @property
    def center(self):
        return self.center_override or self.bounds.centroid

    @property
    def geo_rev_hash(self):
        return hashlib.md5(str(self.geo_rev)).hexdigest()

    @property
    def center_lat_lng(self):
        return self.center.transform(4326, clone=True)

    @property
    def factor_conversions(self):
        """
        Returns a dict for use in eco.py Benefits from eco_benefits_conversion
        """
        benefits_conversion = self.eco_benefits_conversion
        if benefits_conversion:
            return benefits_conversion.get_factor_conversions_config()
        else:
            return None

    @property
    def scss_query_string(self):
        scss_vars = ({k: val
                      for k, val in self.scss_variables.items()
                      if val} if self.scss_variables else {})
        return urlencode(scss_vars)

    @property
    def static_page_names(self):
        from treemap.models import StaticPage  # prevent circular import

        built_in_names = StaticPage.built_in_names()

        custom_names = [
            page.name for page in StaticPage.objects.filter(
                instance=self).exclude(name__in=built_in_names)
        ]

        names = built_in_names + custom_names

        return names

    def update_geo_rev(self):
        qs = Instance.objects.filter(pk=self.id)

        # Use SQL increment in case self.geo_rev is stale
        qs.update(geo_rev=F('geo_rev') + 1)

        # Fetch updated value so callers will have it
        self.geo_rev = qs[0].geo_rev

    def itree_region_codes(self):
        from treemap.models import ITreeRegion

        if self.itree_region_default:
            region_codes = [self.itree_region_default]
        else:
            region_codes = ITreeRegion.objects \
                .filter(geometry__intersects=self.bounds) \
                .values_list('code', flat=True)

        return region_codes

    def itree_regions(self):
        from treemap.models import ITreeRegion  # prevent circular import
        if self.itree_region_default:
            codes = [self.itree_region_default]
        else:
            codes = (ITreeRegion.objects.filter(
                geometry__intersects=self.bounds).values_list('code',
                                                              flat=True))

        return [(code, ITREE_REGIONS.get(code, {}).get('name'))
                for code in codes]

    def has_itree_region(self):
        return bool(self.itree_regions())

    def is_accessible_by(self, user):
        try:
            if self.is_public:
                return True

            # Extension point
            if hasattr(user, 'is_super_admin') and user.is_super_admin():
                return True

            # If a user is not logged in, trying to check
            # user=user raises a type error so I am checking
            # pk instead
            self.instanceuser_set.get(user__pk=user.pk)
            return True
        except ObjectDoesNotExist:
            return False

    def scope_model(self, model):
        qs = model.objects.filter(instance=self)
        return qs

    def feature_enabled(self, feature):
        # Delayed import to prevent circular imports
        from treemap.plugin import feature_enabled
        return feature_enabled(self, feature)

    def seed_with_dummy_default_role(self):
        """
        Instances need roles and roles needs instances... crazy stuff
        we're going to create the needed role below however, we'll temporarily
        use a 'dummy role'. The dummy role has no instance.
        """
        from treemap.audit import Role
        dummy_roles = Role.objects.filter(instance__isnull=True)
        if len(dummy_roles) == 0:
            dummy_role = Role.objects.create(name='empty', rep_thresh=0)
        else:
            dummy_role = dummy_roles[0]

        self.default_role = dummy_role

    def clean(self):
        # We need to work around a bit of a chicken/egg problem here
        # The default API fields reference Stewardship, but the Stewardship
        # UDFs won't exist when the instance is first created.
        # To work around this, we only validate when there is something in the
        # 'config' object, which ignores the default api fields
        if 'mobile_api_fields' in self.config:
            self._validate_mobile_api_fields()

    def _validate_mobile_api_fields(self):
        # Validate that:
        # 1) overall structure is correct
        # 2) each individual group has a header and collection or normal fields
        # 3) Collection UDF groups only contain collection UDFs
        # 4) Collection UDF groups have a 'sort_key', which is present on all
        #    fields for that group
        # 5) no field is referenced more than once
        # 6) all fields referenced exist

        # delayed import to avoid circular references
        from treemap.models import Plot, Tree

        def _truthy_of_type(item, types):
            return item and isinstance(item, types)

        field_groups = self.mobile_api_fields
        errors = set()

        scalar_udfs = {
            udef.full_name: udef
            for udef in udf_defs(self) if not udef.iscollection
        }
        collection_udfs = {
            udef.full_name: udef
            for udef in udf_defs(self) if udef.iscollection
        }

        if not _truthy_of_type(field_groups, (list, tuple)):
            raise ValidationError(
                {'mobile_api_fields': [API_FIELD_ERRORS['no_field_groups']]})

        for group in field_groups:
            if not _truthy_of_type(group.get('header'), basestring):
                errors.add(API_FIELD_ERRORS['group_has_no_header'])

            if ((not _truthy_of_type(group.get('collection_udf_keys'), list)
                 and not _truthy_of_type(group.get('field_keys'), list))):
                errors.add(API_FIELD_ERRORS['group_has_no_keys'])

            elif 'collection_udf_keys' in group and 'field_keys' in group:
                errors.add(API_FIELD_ERRORS['group_has_both_keys'])

            if 'collection_udf_keys' in group:
                sort_key = group.get('sort_key')
                if not sort_key:
                    errors.add(API_FIELD_ERRORS['group_has_no_sort_key'])

                for key in group['collection_udf_keys']:
                    udef = collection_udfs.get(key)
                    if udef is None:
                        errors.add(API_FIELD_ERRORS['group_has_missing_cudf'])
                    elif sort_key not in udef.datatype_by_field:
                        errors.add(
                            API_FIELD_ERRORS['group_has_invalid_sort_key'])

        scalar_fields = [
            key for group in field_groups
            for key in group.get('field_keys', [])
        ]
        collection_fields = [
            key for group in field_groups
            for key in group.get('collection_udf_keys', [])
        ]

        all_fields = scalar_fields + collection_fields

        if len(all_fields) != len(set(all_fields)):
            errors.add(API_FIELD_ERRORS['duplicate_fields'])

        for field in scalar_fields:
            if not re.match(r'(?:plot|tree)[.].*', field):
                errors.add(API_FIELD_ERRORS['invalid_field'] %
                           {'field': field})
                continue

            model_name, name = field.split('.', 1)  # maxsplit of 1
            Model = Plot if model_name == 'plot' else Tree
            standard_fields = Model._meta.get_all_field_names()

            if ((name not in standard_fields and field not in scalar_udfs)):
                errors.add(API_FIELD_ERRORS['missing_field'])

        if errors:
            raise ValidationError({'mobile_api_fields': errors})

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

        self.url_name = self.url_name.lower()

        super(Instance, self).save(*args, **kwargs)
Пример #29
0
class Locazione(ConMarcaTemporale, models.Model):

    class Meta:
        verbose_name = "Locazione Geografica"
        verbose_name_plural = "Locazioni Geografiche"
        permissions = (
            ("view_locazione", "Can view locazione"),
        )

    indirizzo = models.CharField("Indirizzo", max_length=255, db_index=True)

    objects = models.GeoManager()
    geo = models.PointField(blank=True, default='POINT(0.0 0.0)', db_index=True,
                            spatial_index=True, srid=4326, geography=True)

    via = models.CharField("Via", max_length=64, blank=True)
    civico = models.CharField("Civico", max_length=16, blank=True)
    comune = models.CharField("Comune", max_length=64, blank=True, db_index=True)
    provincia = models.CharField("Provincia", max_length=64, blank=True, db_index=True)
    provincia_breve = models.CharField("Provincia (breve)", max_length=64, blank=True, db_index=True)
    regione = models.CharField("Regione", max_length=64, blank=True, db_index=True)
    cap = models.CharField("CAP", max_length=32, blank=True, db_index=True)
    stato = CountryField("Stato", default="IT")

    def __str__(self):
        return self.indirizzo

    @classmethod
    def scomponi_indirizzo(cls, oggetto):
        INDIRIZZO_PARTI = (
             ('civico',  ('street_number', 'long_name')),
             ('via', ('route', 'long_name')),
             ('comune', ('locality', 'long_name')),
             ('provincia', ('administrative_area_level_2', 'long_name')),
             ('provincia_breve', ('administrative_area_level_2', 'short_name')),
             ('regione', ('administrative_area_level_1', 'long_name')),
             ('stato', ('country', 'short_name')),
             ('cap', ('postal_code', 'long_name'))
        )
        parti = {a[0]: None for a in INDIRIZZO_PARTI}
        for (parte, nomenclatura) in INDIRIZZO_PARTI:
            (a, b) = nomenclatura
            for p in oggetto['address_components']:
                if not a in p['types']:
                    continue
                parti[parte] = p[b].replace('Provincia di ', '').replace('Province of ', '')\
                    .replace('Provincia della ', 'La ').replace('Provincia dell\'', 'L\'')
        return parti

    @classmethod
    def controlla_posizione(cls, coordinate):
        """
        Valida le coordinate. L'unico controllo possibile è che le coordinate non devono essere
        entrambe zero
        :param coordinate: vettore lat / lng ritornato da google geocoding
        :return: coordinate inalterate o '0'
        """
        try:
            if coordinate['lat'] and coordinate['lng']:
                return coordinate
        except (KeyError, ValueError, TypeError):
            return '0'
        return '0'

    @classmethod
    def cerca(cls, indirizzo):
        """
        Usa le API di Google (Geocode) per cercare l'indirizzo,
        ritorna una stringa (indirizzo formattato) per ogni risultato.

        :param indirizzo: Indirizzo da cercare
        :return: Lista di risultati.
        """
        try:
            gmaps = googlemaps.Client(key=GOOGLE_KEY)

        except ValueError:
            # API key not configured
            logger.warning("Chiave API Google non configurata. Le ricerche geografiche non ritorneranno "
                           "alcun risultato.")
            return []

        risultati = gmaps.geocode(indirizzo, region="it", language="it")
        return [
            (x['formatted_address'], cls.controlla_posizione(x['geometry']['location']),
             cls.scomponi_indirizzo(x))
            for x in risultati
        ]

    @classmethod
    def oggetto(self, indirizzo):
        """
        Cerca un oggetto per indirizzo. Se esistente, ritorna
        la referenza. Altrimenti, interroga Google, scompone
        l'indirizzo e ritorna una nuova istanza di Locazione (salvata).
        :param indirizzo: Una stringa da ricercare.
        :return: Oggetto Locazione o None se non trovato.
        """
        if not indirizzo:
            return None

        j = Locazione.objects.filter(indirizzo=indirizzo).first()
        if j:
            return j

        risultati = Locazione.cerca(indirizzo)
        if not len(risultati):
            return None
        risultato = risultati[0]

        j = Locazione.objects.filter(indirizzo=risultato[0]).first()
        if j:
            return j

        l = Locazione(
            indirizzo=risultato[0],
            geo=Point(risultato[1]['lng'], risultato[1]['lat']),
            **{k: risultato[2][k] if risultato[2][k] else '' for k in risultato[2]}
        )
        l.save()
        return l

    def cerca_e_aggiorna(self):
        """
        Cerca indirizzo in 'indirizzo' e aggiorna indirizzo e coordinate.
        """
        risultati = Locazione.cerca(self.indirizzo)
        if not len(risultati):
            return False
        risultato = risultati[0]

        self.indirizzo = risultato[0]
        self.geo = Point(risultato[1]['lng'], risultato[1]['lat'])
        valori = {k: risultato[2][k] if risultato[2][k] else '' for k in risultato[2]}
        for k in valori:
            setattr(self, k, valori[k])
        return self.save()

    @property
    def formattato(self):
        return self.indirizzo.replace("Italy", "Italia")
Пример #30
0
class Layer(models.Model):
    """
    A layer object that can be added to any map.
    """

    name = models.CharField(
        max_length=200, help_text='Name that will be displayed within GeoQ')
    type = models.CharField(choices=SERVICE_TYPES, max_length=75)
    url = models.CharField(
        help_text=
        'URL of service. If WMS or ESRI, can be any valid URL. Otherwise, the URL will require a local proxy',
        max_length=500)
    layer = models.CharField(
        max_length=800,
        null=True,
        blank=True,
        help_text=
        'Layer names can sometimes be comma-separated, and are not needed for data layers (KML, GeoRSS, GeoJSON...)'
    )
    image_format = models.CharField(
        null=True,
        blank=True,
        choices=IMAGE_FORMATS,
        max_length=75,
        help_text=
        'The MIME type of the image format to use for tiles on WMS layers (image/png, image/jpeg image/gif...). Double check that the server exposes this exactly - some servers push png instead of image/png.'
    )
    styles = models.CharField(
        null=True,
        blank=True,
        max_length=200,
        help_text=
        'The name of a style to use for this layer (only useful for WMS layers if the server exposes it.)'
    )
    transparent = models.BooleanField(
        default=True,
        help_text=
        'If WMS or overlay, should the tiles be transparent where possible?')
    refreshrate = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name="Layer Refresh Rate",
        help_text=
        'Layer refresh rate in seconds for vector/data layers (will not refresh WMS layers)'
    )
    description = models.TextField(
        max_length=800,
        null=True,
        blank=True,
        help_text=
        'Text to show in layer chooser, please be descriptive - this will soon be searchable'
    )
    attribution = models.CharField(
        max_length=200,
        null=True,
        blank=True,
        help_text=
        "Attribution from layers to the map display (will show in bottom of map when layer is visible)."
    )
    token = models.CharField(
        max_length=400,
        null=True,
        blank=True,
        help_text=
        'Authentication token, if required (usually only for secure layer servers)'
    )

    ## Advanced layer options
    objects = models.GeoManager()
    extent = models.PolygonField(null=True,
                                 blank=True,
                                 help_text='Extent of the layer.')
    layer_parsing_function = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        help_text=
        'Advanced - The javascript function used to parse a data service (GeoJSON, GeoRSS, KML), needs to be an internally known parser. Contact an admin if you need data parsed in a new way.'
    )
    enable_identify = models.BooleanField(
        default=False,
        help_text=
        'Advanced - Allow user to click map to query layer for details. The map server must support queries for this layer.'
    )
    info_format = models.CharField(
        max_length=75,
        null=True,
        blank=True,
        choices=INFO_FORMATS,
        help_text='Advanced - what format the server returns for an WMS-I query'
    )
    root_field = models.CharField(
        max_length=100,
        null=True,
        blank=True,
        help_text=
        'Advanced - For WMS-I (queryable) layers, the root field returned by server. Leave blank for default (will usually be "FIELDS" in returned XML).'
    )
    fields_to_show = models.CharField(
        max_length=200,
        null=True,
        blank=True,
        help_text=
        'Fields to show when someone uses the identify tool to click on the layer. Leave blank for all.'
    )
    downloadableLink = models.URLField(
        max_length=400,
        null=True,
        blank=True,
        help_text=
        'URL of link to supporting tool (such as a KML document that will be shown as a download button)'
    )
    layer_params = JSONField(
        null=True,
        blank=True,
        help_text=
        'JSON key/value pairs to be sent to the web service.  ex: {"crs":"urn:ogc:def:crs:EPSG::4326"}'
    )
    dynamic_params = JSONField(
        null=True,
        blank=True,
        help_text=
        'URL Variables that may be modified by the analyst. ex: "date"')
    spatial_reference = models.CharField(
        max_length=32,
        blank=True,
        null=True,
        default="EPSG:4326",
        help_text=
        'The spatial reference of the service.  Should be in ESPG:XXXX format.'
    )
    constraints = models.TextField(
        null=True,
        blank=True,
        help_text='Constrain layer data displayed to certain feature types')
    disabled = models.BooleanField(
        default=False,
        blank=True,
        help_text="If unchecked, Don't show this layer when listing all layers"
    )
    layer_info_link = models.URLField(
        null=True,
        blank=True,
        help_text='URL of info about the service, or a help doc or something',
        max_length=500)
    created_at = models.DateTimeField(auto_now_add=True, null=True)
    updated_at = models.DateTimeField(auto_now_add=True, null=True)

    ## Primarily for http://trac.osgeo.org/openlayers/wiki/OpenLayersOptimization
    additional_domains = models.TextField(
        null=True,
        blank=True,
        help_text=
        'Semicolon seperated list of additional domains for the layer. Only used if you want to cycle through domains for load-balancing'
    )

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

    def get_layer_urls(self):
        """
        Returns a list of urls for the layer.
        """
        urls = []

        if getattr(self, 'additional_domains'):
            map(urls.append,
                (domain
                 for domain in self.additional_domains.split(";") if domain))

        return urls

    def get_absolute_url(self):
        return reverse('layer-update', args=[self.id])

    def get_layer_params(self):
        """
        Returns the layer_params attribute, which should be json
        """
        return self.layer_params

    def layer_json(self):
        return {
            "id": self.id,
            "name": self.name,
            "format": self.image_format,
            "type": self.type,
            "url": self.url,
            "subdomains": self.get_layer_urls(),
            "layer": self.layer,
            "transparent": self.transparent,
            "layerParams": self.layer_params,
            "dynamicParams": self.dynamic_params,
            "refreshrate": self.refreshrate,
            "token": self.token,
            "attribution": self.attribution,
            "spatialReference": self.spatial_reference,
            "layerParsingFunction": self.layer_parsing_function,
            "enableIdentify": self.enable_identify,
            "rootField": self.root_field,
            "infoFormat": self.info_format,
            "fieldsToShow": self.fields_to_show,
            "description": self.description,
            "downloadableLink": self.downloadableLink,
            "layer_info_link": self.layer_info_link,
            "styles": self.styles,
        }

    class Meta:
        ordering = ["name"]