from django.db import connection from django.contrib.gis.db import models from django.contrib.gis.geos import Polygon # Create your models here. class AuthorityRecord(models.Model): uri = models.CharField(max_length=512) preferred_name = models.CharField(max_length=255) def __unicode__(self): return self.preferred_name class FeatureSearchManager(models.GeoManager): def set_threshold(self, threshold): """Set the limit for trigram similarity matching.""" cursor = connection.cursor cursor.execute("""SELECT set_limit(%f)""" % threshold) def overlaps(self, (minx, miny, maxx, maxy), text=None, srid=4326): bbox = Polygon(((minx,miny),(minx,maxy),(maxx,maxy),(maxx,miny),(minx,miny)),srid=srid) if srid != 4326: bbox.transform(4326) # convert to lon/lat qset = super(FeatureSearchManager, self).get_query_set().filter(geometry_bboverlaps=bbox) if text: text = text.replace("'", "''") # escape the ' # use the pg_trgm index qset = qset.extra(where="[preferred_name %% '%s']" % text) return qset class Feature(models.Model): authority_record = models.ForeignKey(AuthorityRecord, null=True, blank=True) url = models.CharField(max_length=512, unique=True, verbose_name="URI") preferred_name = models.CharField(max_length=512) feature_type = models.ForeignKey("FeatureType", null=True, blank=True) admin1 = models.CharField(max_length=2, blank=True, verbose_name="State") admin2 = models.CharField(max_length=255, blank=True, verbose_name="County") geometry = models.GeometryField() is_primary = models.BooleanField(default=True) time_frame = models.ForeignKey("TimeFrame", null=True, blank=True) relationships = models.ManyToManyField("Feature", through='Relationship', blank=True) objects = models.GeoManager() search = FeatureSearchManager() class Meta: ordering = ['preferred_name'] def __unicode__(self): return self.preferred_name def feature_type_name(self): return "%s: %s" % (self.feature_type.code, self.feature_type.name,) feature_type_name.short_description = "Feature Type" def time_start(self): tf = self.time_frame if tf is not None: return str(tf.start_date) else: return '' time_start.short_description = "Start Date" def time_end(self): tf = self.time_frame if tf is not None: return str(tf.end_sate) else: return '' time_end.short_description = "End Date" def similar_features(self, max_distance=15000, scale_factor=2000): cursor = connection.cursor() name = unicode(self).replace("'", "''") # escape ' cursor.execute(""" SELECT *, %f * similarity / distance AS score FROM ( SELECT url, preferred_name, feature_type, admin1, admin2, is_primary, similarity(preferred_name, '%s') AS similarity, st_distance_sphere(geometry, '%s') AS distance FROM places_feature WHERE geometry && st_buffer('%s', %f) AND preferred_name % '%s' ) AS whatever WHERE %f * similarity / distance >= 1.0 ORDER BY similarity / distance DESC""" % (scale_factor, name, self.geometry.wkt, self.geometry.wkt, max_distance*0.00001, name, scale_factor) ) result_list = [] fields = ('url', 'preferred_name', 'feature_type', 'admin1', 'admin2', 'is_primary') for row in cursor.fetchall(): vals = dict(zip(fields, row[:len(fields)])) p = type(self)(**vals) p.similarity = row[-3] p.distance = row[-2] p.score = row[-1] result_list.append(p) return result_list LANGUAGE_CHOICES = ( ('en', 'English'), ('es', 'Spanish'), ) NAME_TYPE_CHOICES = ( ('official', 'official'), ('historic', 'historic'), ('colloquial', 'colloquial'), ('-blank-', '-blank-'), ) class Name(models.Model): feature = models.ForeignKey(Feature) text = models.CharField(max_length=512) language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES) name_type = models.CharField(max_length=64, choices=NAME_TYPE_CHOICES) def __unicode__(self): return self.text GRANULARITY_CHOICES = ( ('day', 'day'), ('month', 'month'), ('year', 'year'), ('decade', 'decade'), ('century', 'century'), ) class TimeFrame(models.Model): description = models.CharField(max_length=100, blank=True) start_date = models.DateField() end_date = models.DateField() #add default to now start_granularity = models.CharField(max_length=64, choices=GRANULARITY_CHOICES) end_granularity = models.CharField(max_length=64, choices=GRANULARITY_CHOICES) def __unicode__(self): return self.description class FeatureType(models.Model): feature_class = models.CharField(max_length=1) code = models.CharField(max_length=5, unique=True) name = models.CharField(max_length=128) description = models.TextField() class Meta: ordering = ['code'] def __unicode__(self): return self.code + ": " + self.name RELATIONSHIP_CHOICES = ( ('conflates', 'conflates'), ('contains', 'contains'), ('subsumes', 'subsumes'), ('supersedes', 'supersedes'), ) class Relationship(models.Model): feature1 = models.ForeignKey(Feature, related_name="feauture_from") feature2 = models.ForeignKey(Feature, related_name="feature_to") relationship_type = models.CharField(max_length=64, choices=RELATIONSHIP_CHOICES) ''' class Place(models.Model): url = models.CharField(max_length=255, primary_key=True, unique=True) name = models.CharField(max_length=255) fcode = models.ForeignKey("FeatureCode") country = models.CharField(max_length=2) admin1 = models.CharField(max_length=2) point = models.PointField() def __unicode__(self): return self.name class FeatureCode(models.Model): fcode = models.CharField(max_length=10, primary_key=True, unique=True) letter = models.CharField(max_length=2) short_name = models.CharField(max_length=100) description = models.TextField() def __unicode__(self): return self.fcode + ": " + self.short_name '''