gazetteer/gazetteer/places/models.py
2011-08-27 18:26:00 -07:00

187 lines
6.3 KiB
Python

from django.db import connection
from django.contrib.gis.db import models, manager
# 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(manager.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, bbox, text=None):
bbox = 'POLYGON(((%f %f, %f %f, %f %f, %f %f, %f %f)))' % (bbox[0], bbox[1], bbox[2], bbox[1], bbox[2], bbox[3], bbox[0], bbox[3], bbox[0], bbox[1])
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 = models.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, self.geometry,
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
'''