Skip to content

Commit

Permalink
Merge pull request #70 from fpdcc/gis-models
Browse files Browse the repository at this point in the history
Configure second GIS database and router, add example model and skeleton models for remainder of quercus schema
  • Loading branch information
hancush authored Dec 3, 2021
2 parents 2bf56b2 + 8ca24c5 commit 642ca02
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 18 deletions.
191 changes: 190 additions & 1 deletion asset_dashboard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def total_score(self):
return total_score

def add_score_to_queryset(self):
'''we'll need to add the total scores to the queryset'''
"""we'll need to add the total scores to the queryset"""

def __str__(self):
return self.project.name
Expand Down Expand Up @@ -248,3 +248,192 @@ class DummyProject(models.Model):
def __str__(self):
""""String for representing the model object"""
return self.name


class GISModel(models.Model):
"""
Migrations will not be created for models inheriting from this base class
because of allow_migrate() method in the GISRouter.
"""

class Meta:
abstract = True
managed = False
app_label = 'asset_dashboard_gis'


class NaturePreserves(GISModel):

class Meta(GISModel.Meta):
db_table = '"quercus"."nature_preserves"'

id = models.AutoField(primary_key=True, db_column='nature_preserves_id')
site_name = models.CharField(max_length=254)

def __str__(self):
return self.site_name


class Buildings(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.buildings'


class Holdings(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.holdings'


class LicenseIGA(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.license_iga'


class MowAreaDB(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.mow_area_db'


class MwrdFpdLease(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.mwrd_fpd_lease'


class Names(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.names'


class ParkingEntrance(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.parking_entrance'


class ParkingEntranceInfo(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.parking_entrance_info'


class ParkingEval17(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.parking_eval17'


class ParkingLots(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.parking_lots'


class PicnicGroves(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.picnicgroves'


class PoiAmenity(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.poi_amenity'


class PoiDesc(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.poi_desc'


class PoiInfo(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.poi_info'


class PoiToTrails(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.poi_to_trails'


class PointsOfInterest(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.pointsofinterest'


class Regions(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.regions'


class Signage(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.signage'


class TrailSubsystemLu(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trail_subsystem_lu'


class Trails(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trails'


class TrailsAmenity(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trails_amenity'


class TrailsDesc(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trails_desc'


class TrailsInfo(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trails_info'


class TrailsMaintenance(GISModel):

class Meta(GISModel.Meta):
db_table = 'quercus.trails_maintenace'


class Zones(GISModel):
class Meta(GISModel.Meta):
db_table = 'quercus.zones'

# fpdcc=# \d quercus.zones
# Table "quercus.zones"
# Column | Type | Collation | Nullable | Default
# --------------+-----------------------------+-----------+----------+------------------------------------------------
# zone_id | integer | | not null | nextval('quercus.zones_zone_id_seq'::regclass)
# zone | character varying(10) | | |
# abbreviation | character varying(2) | | |
# geom | geometry(MultiPolygon,3435) | | |
# Indexes:
# "zones_pkey" PRIMARY KEY, btree (zone_id)

# zones_pk = models.IntegerField(primary_key=True)
zone_id = models.IntegerField(primary_key=True)
zone = models.CharField(max_length=10)
geom = models.MultiPolygonField(srid=3435) # TODO: i think this was srid? `geom | geometry(MultiPolygon,3435)`
52 changes: 52 additions & 0 deletions asset_dashboard/routers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class GISRouter:
"""
Route queries for tables in the specied schemas to the "fp_postgis" database.
"""
GIS_DB_ALIAS = 'fp_postgis'
GIS_APP_LABEL = 'asset_dashboard_gis'

def db_for_read(self, model, **hints):
if model._meta.app_label == self.GIS_APP_LABEL:
return self.GIS_DB_ALIAS
return None

def db_for_write(self, model, **hints):
"""
Specify where to write GIS data so we can create test data using the
ORM.
N.b., we probably should not modify CCFP's data. This method assumes
that they've granted us read-only access, i.e., the database will raise
an exception for any write requests against the live server.
"""
if model._meta.app_label == self.GIS_APP_LABEL:
return self.GIS_DB_ALIAS
return None

def allow_relation(self, obj1, obj2, **hints):
"""
From the Django docs:
> If no router has an opinion (i.e. all routers return None), only
relations within the same database are allowed.
https://docs.djangoproject.com/en/3.2/topics/db/multi-db/#allow_relation
Thus, this should disallow the relation of tables in the specified
schemas to objects in the default database. This should be ok because
we will copy necessary GIS data to the default database for subsequent
relation and manipulation.
"""
return None

def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Only create and run migrations for models that are not marked by the
GIS_APP_LABEL. This prevents the creation of migrations for GIS models
and stops Django from trying to create a django_migrations table in the
GIS_DB_ALIAS database, since we won't have write access. Reference:
https://stackoverflow.com/a/43553063
"""
if app_label == self.GIS_APP_LABEL:
return False
return db == 'default'
22 changes: 15 additions & 7 deletions asset_dashboard/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,22 @@
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {}
DATABASES = {
'default': dj_database_url.parse(
os.getenv('DATABASE_URL', 'postgis://postgres:postgres@postgres:5432/database'),
conn_max_age=600,
ssl_require=True if os.getenv('POSTGRES_REQUIRE_SSL') else False,
engine='django.contrib.gis.db.backends.postgis'
),
'fp_postgis': dj_database_url.parse(
os.getenv('GIS_DATABASE_URL', 'postgis://postgres:postgres@fp-postgis:5432/fpdcc'),
conn_max_age=600,
ssl_require=True if os.getenv('POSTGRES_REQUIRE_SSL') else False,
engine='django.contrib.gis.db.backends.postgis'
),
}

DATABASES['default'] = dj_database_url.parse(
os.getenv('DATABASE_URL', 'postgis://postgres:postgres@postgres:5432/database'),
conn_max_age=600,
ssl_require=True if os.getenv('POSTGRES_REQUIRE_SSL') else False,
engine='django.contrib.gis.db.backends.postgis'
)
DATABASE_ROUTERS = ['asset_dashboard.routers.GISRouter']

# Caching
# https://docs.djangoproject.com/en/3.0/topics/cache/
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ services:
depends_on:
postgres:
condition: service_healthy
fp-postgis:
condition: service_healthy
volumes:
# Mount the development directory as a volume into the container, so
# Docker automatically recognizes your changes.
Expand Down
Loading

0 comments on commit 642ca02

Please sign in to comment.