diff --git a/geodjango/samplelocations/admin.py b/geodjango/samplelocations/admin.py index 4458283..9f126f5 100644 --- a/geodjango/samplelocations/admin.py +++ b/geodjango/samplelocations/admin.py @@ -3,7 +3,7 @@ from django import forms from django.contrib.gis.admin import GISModelAdmin from django.contrib.gis.geos import Point -from samplelocations.models import Location, Thing, WellThing, SpringThing, Location_Thing_Junction, Sensor, Datastream, Observation, \ +from samplelocations.models import Location, Thing, Location_Thing_Junction, Sensor, Datastream, Observation, \ GroundwaterLevelObservation, Sample class LocationForm(forms.ModelForm): @@ -29,14 +29,6 @@ class LocationAdmin(GISModelAdmin): class ThingAdmin(ModelAdmin): pass -@admin.register(WellThing) -class WellThingAdmin(ModelAdmin): - pass - -@admin.register(SpringThing) -class SpringThingAdmin(ModelAdmin): - pass - @admin.register(Location_Thing_Junction) class LocationThingJunctionAdmin(ModelAdmin): pass @@ -61,6 +53,14 @@ class GroundwaterLevelObservationAdmin(ModelAdmin): class SampleAdmin(ModelAdmin): pass +# @admin.register(WellThing) +# class WellThingAdmin(ModelAdmin): +# pass + +# @admin.register(SpringThing) +# class SpringThingAdmin(ModelAdmin): +# pass + #admin.site.register(Lexicon) #admin.site.register(WellScreen) #admin.site.register(Equipment) diff --git a/geodjango/samplelocations/migrations/0001_initial.py b/geodjango/samplelocations/migrations/0001_initial.py index d6c175a..fafbb0d 100644 --- a/geodjango/samplelocations/migrations/0001_initial.py +++ b/geodjango/samplelocations/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.3 on 2025-06-26 15:14 +# Generated by Django 5.2.3 on 2025-07-30 18:04 import django.contrib.gis.db.models.fields import django.db.models.deletion @@ -14,114 +14,124 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Contact', + name='Datastream', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('email', models.EmailField(max_length=254)), - ('phone', models.CharField(blank=True, max_length=20, null=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), + ('datastream_id', models.BigAutoField(primary_key=True, serialize=False)), + ('observed_property', models.CharField(max_length=100)), + ('release_status', models.BooleanField(default=False)), ], - options={ - 'verbose_name': 'Contact', - 'verbose_name_plural': 'Contacts', - 'ordering': ['name'], - }, ), migrations.CreateModel( - name='Lexicon', + name='Observation', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ('description', models.CharField(blank=True, max_length=255, null=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), + ('observation_id', models.BigAutoField(primary_key=True, serialize=False)), + ('observed_value', models.FloatField(help_text='The value of the observation')), + ('release_status', models.BooleanField(default=False)), + ('datastream_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='observations', to='samplelocations.datastream', verbose_name='related datastream')), ], - options={ - 'verbose_name': 'Lexicon', - 'verbose_name_plural': 'Lexicons', - 'ordering': ['name'], - }, ), migrations.CreateModel( - name='Owner', + name='Location', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('description', models.CharField(blank=True, max_length=255, null=True)), + ('location_id', models.BigAutoField(primary_key=True, serialize=False)), + ('coordinate', django.contrib.gis.db.models.fields.PointField(dim=3, srid=4326)), ('date_created', models.DateTimeField(auto_now_add=True)), - ('contact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owners', to='samplelocations.contact')), ], options={ - 'verbose_name': 'Owner', - 'verbose_name_plural': 'Owners', - 'ordering': ['name'], + 'verbose_name': 'Location', + 'verbose_name_plural': 'Locations', + 'db_table_comment': "This table stores point locations on the earth's surface", }, ), migrations.CreateModel( - name='SampleLocation', + name='Sample', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('description', models.CharField(blank=True, max_length=255, null=True)), - ('visible', models.BooleanField(default=False)), - ('point', django.contrib.gis.db.models.fields.PointField(srid=4326)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='samplelocations', to='samplelocations.owner')), + ('sample_id', models.BigAutoField(primary_key=True, serialize=False)), + ('sample_matrix', models.CharField(choices=[('GW', 'Groundwater'), ('S', 'Soil')], default='GW', max_length=2, verbose_name='type of sample')), + ('sample_date', models.DateTimeField()), + ('sample_notes', models.TextField(blank=True, null=True)), ], - options={ - 'verbose_name': 'Sample Location', - 'verbose_name_plural': 'Sample Locations', - 'ordering': ['name'], - }, ), migrations.CreateModel( - name='Equipment', + name='Sensor', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('equipment_type', models.CharField(max_length=50)), - ('model', models.CharField(max_length=50)), - ('serial_no', models.CharField(max_length=50)), - ('date_installed', models.DateTimeField(blank=True, null=True)), - ('date_removed', models.DateTimeField(blank=True, null=True)), - ('recording_interval', models.IntegerField(blank=True, null=True)), - ('equipment_notes', models.CharField(blank=True, max_length=50, null=True)), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='equipment', to='samplelocations.samplelocation')), + ('sensor_id', models.BigAutoField(primary_key=True, serialize=False)), + ('name', models.CharField(blank=True, max_length=100, null=True)), + ('serial_number', models.CharField(blank=True, max_length=50, null=True)), + ('install_date', models.DateTimeField(blank=True, null=True)), + ('model', models.CharField(blank=True, max_length=50, null=True)), + ('notes', models.TextField(blank=True, null=True)), ], ), migrations.CreateModel( - name='Spring', + name='GroundwaterLevelObservation', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.CharField(blank=True, max_length=255, null=True)), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='springs', to='samplelocations.samplelocation')), + ('groundwater_level_observation_id', models.BigAutoField(primary_key=True, serialize=False)), + ('observation_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, related_name='groundwater_level_observations', to='samplelocations.observation', verbose_name='related observation')), ], + bases=('samplelocations.observation',), ), migrations.CreateModel( - name='Well', + name='Location_Thing_Junction', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ose_pod_id', models.CharField(blank=True, max_length=50, null=True)), - ('api_id', models.CharField(blank=True, default='', max_length=50)), - ('usgs_id', models.CharField(blank=True, max_length=50, null=True)), - ('well_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('hole_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('casing_diameter', models.FloatField(blank=True, help_text='inches', null=True)), - ('casing_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('casing_description', models.CharField(blank=True, max_length=50, null=True)), - ('construction_notes', models.CharField(blank=True, max_length=250, null=True)), - ('formation_zone', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wells_by_formation', to='samplelocations.lexicon')), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wells', to='samplelocations.samplelocation')), - ('well_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wells_by_type', to='samplelocations.lexicon')), + ('effective_start', models.DateTimeField()), + ('effective_end', models.DateTimeField()), + ('location_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations_things', to='samplelocations.location', verbose_name='related location')), ], + options={ + 'db_table_comment': 'Junction table linking Location and Thing models', + }, + ), + migrations.AddField( + model_name='observation', + name='sample', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='observations', to='samplelocations.sample', verbose_name='related sample'), + ), + migrations.AddField( + model_name='datastream', + name='sensor_id', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='datastreams', to='samplelocations.sensor', verbose_name='related sensor'), ), migrations.CreateModel( - name='WellScreen', + name='Thing', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('screen_depth_top', models.FloatField(help_text='feet below ground surface')), - ('screen_depth_bottom', models.FloatField(help_text='feet below ground surface')), - ('screen_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='well_screens_by_type', to='samplelocations.lexicon')), - ('well', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='screens', to='samplelocations.well')), + ('thing_id', models.BigAutoField(primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100, unique=True)), + ('thing_type', models.CharField(choices=[('W', 'Well'), ('S', 'Spring')], default='W', max_length=2, verbose_name='type of thing')), + ('release_status', models.BooleanField(default=False)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('well_depth_ft', models.FloatField(blank=True, help_text='well depth feet below ground surface', null=True)), + ('hole_depth_ft', models.FloatField(blank=True, help_text='hole depth feet below ground surface', null=True)), + ('casing_diameter_ft', models.FloatField(blank=True, help_text='casing diameter in ft', null=True)), + ('casing_depth_ft', models.FloatField(blank=True, help_text='casing depth feet below ground surface', null=True)), + ('casing_description', models.CharField(blank=True, max_length=50, null=True)), + ('construction_notes', models.TextField(blank=True, null=True)), + ('spring_type', models.CharField(blank=True, max_length=255, null=True)), + ('location_id', models.ManyToManyField(related_name='things', through='samplelocations.Location_Thing_Junction', to='samplelocations.location', verbose_name='related location')), ], + options={ + 'verbose_name': 'Thing', + 'verbose_name_plural': 'Things', + }, + ), + migrations.AddField( + model_name='sample', + name='thing_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='samples', to='samplelocations.thing', verbose_name='related thing'), + ), + migrations.AddField( + model_name='location_thing_junction', + name='thing_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations_things', to='samplelocations.thing', verbose_name='related thing'), + ), + migrations.AddField( + model_name='datastream', + name='thing_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='datastreams', to='samplelocations.thing', verbose_name='related thing'), + ), + migrations.AddConstraint( + model_name='location_thing_junction', + constraint=models.UniqueConstraint(fields=('location_id', 'thing_id'), name='unique_location_thing'), ), ] diff --git a/geodjango/samplelocations/migrations/0002_datastream_observation_location_sample_sensor_thing_and_more.py b/geodjango/samplelocations/migrations/0002_datastream_observation_location_sample_sensor_thing_and_more.py deleted file mode 100644 index 1c34efa..0000000 --- a/geodjango/samplelocations/migrations/0002_datastream_observation_location_sample_sensor_thing_and_more.py +++ /dev/null @@ -1,213 +0,0 @@ -# Generated by Django 5.2.3 on 2025-07-11 16:53 - -import django.contrib.gis.db.models.fields -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('samplelocations', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Datastream', - fields=[ - ('datastream_id', models.BigAutoField(primary_key=True, serialize=False)), - ('observed_property', models.CharField(max_length=100)), - ('release_status', models.BooleanField(default=False)), - ], - ), - migrations.CreateModel( - name='Observation', - fields=[ - ('observation_id', models.BigAutoField(primary_key=True, serialize=False)), - ('observed_value', models.FloatField(help_text='The value of the observation')), - ('release_status', models.BooleanField(default=False)), - ('datastream', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='observations', to='samplelocations.datastream', verbose_name='related datastream')), - ], - ), - migrations.CreateModel( - name='Location', - fields=[ - ('location_id', models.BigAutoField(primary_key=True, serialize=False)), - ('coordinate', django.contrib.gis.db.models.fields.PointField(dim=3, srid=4326)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ], - options={ - 'verbose_name': 'Location', - 'verbose_name_plural': 'Locations', - 'db_table_comment': "This table stores point locations on the earth's surface", - }, - ), - migrations.CreateModel( - name='Sample', - fields=[ - ('sample_id', models.BigAutoField(primary_key=True, serialize=False)), - ('sample_date', models.DateTimeField()), - ('sample_notes', models.TextField(blank=True, null=True)), - ], - ), - migrations.CreateModel( - name='Sensor', - fields=[ - ('sensor_id', models.BigAutoField(primary_key=True, serialize=False)), - ('serial_number', models.CharField(blank=True, max_length=50, null=True)), - ('install_date', models.DateTimeField(blank=True, null=True)), - ('model', models.CharField(blank=True, max_length=50, null=True)), - ('notes', models.TextField(blank=True, null=True)), - ], - ), - migrations.CreateModel( - name='Thing', - fields=[ - ('thing_id', models.BigAutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=100, unique=True)), - ('release_status', models.BooleanField(default=False)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ], - options={ - 'verbose_name': 'Thing', - 'verbose_name_plural': 'Things', - }, - ), - migrations.RemoveField( - model_name='owner', - name='contact', - ), - migrations.RemoveField( - model_name='equipment', - name='location', - ), - migrations.RemoveField( - model_name='well', - name='well_type', - ), - migrations.RemoveField( - model_name='wellscreen', - name='screen_type', - ), - migrations.RemoveField( - model_name='well', - name='formation_zone', - ), - migrations.RemoveField( - model_name='samplelocation', - name='owner', - ), - migrations.RemoveField( - model_name='well', - name='location', - ), - migrations.RemoveField( - model_name='spring', - name='location', - ), - migrations.RemoveField( - model_name='wellscreen', - name='well', - ), - migrations.CreateModel( - name='GroundwaterLevelObservation', - fields=[ - ('groundwater_level_observation_id', models.BigAutoField(primary_key=True, serialize=False)), - ('observation_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, related_name='groundwater_level_observations', to='samplelocations.observation', verbose_name='related observation')), - ], - bases=('samplelocations.observation',), - ), - migrations.CreateModel( - name='Location_Thing_Junction', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('effective_start', models.DateTimeField()), - ('effective_end', models.DateTimeField()), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations_things', to='samplelocations.location', verbose_name='related location')), - ], - options={ - 'db_table_comment': 'Junction table linking Location and Thing models', - }, - ), - migrations.AddField( - model_name='observation', - name='sample', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='observations', to='samplelocations.sample', verbose_name='related sample'), - ), - migrations.AddField( - model_name='datastream', - name='sensor_id', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='datastreams', to='samplelocations.sensor', verbose_name='related sensor'), - ), - migrations.CreateModel( - name='SpringThing', - fields=[ - ('springthing_id', models.BigAutoField(primary_key=True, serialize=False)), - ('thing_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, related_name='springthings', to='samplelocations.thing', verbose_name='related thing')), - ('description', models.CharField(blank=True, max_length=255, null=True)), - ], - bases=('samplelocations.thing',), - ), - migrations.CreateModel( - name='WellThing', - fields=[ - ('wellthing_id', models.BigAutoField(primary_key=True, serialize=False)), - ('thing_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, related_name='wellthings', to='samplelocations.thing', verbose_name='related thing')), - ('well_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('hole_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('casing_diameter', models.FloatField(blank=True, help_text='inches', null=True)), - ('casing_depth', models.FloatField(blank=True, help_text='feet below ground surface', null=True)), - ('casing_description', models.CharField(blank=True, max_length=50, null=True)), - ('construction_notes', models.TextField(blank=True, null=True)), - ], - bases=('samplelocations.thing',), - ), - migrations.AddField( - model_name='thing', - name='location', - field=models.ManyToManyField(related_name='things', through='samplelocations.Location_Thing_Junction', to='samplelocations.location', verbose_name='related location'), - ), - migrations.AddField( - model_name='sample', - name='thing', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='samples', to='samplelocations.thing', verbose_name='related thing'), - ), - migrations.AddField( - model_name='location_thing_junction', - name='thing', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations_things', to='samplelocations.thing', verbose_name='related thing'), - ), - migrations.AddField( - model_name='datastream', - name='thing', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='datastreams', to='samplelocations.thing', verbose_name='related thing'), - ), - migrations.DeleteModel( - name='Contact', - ), - migrations.DeleteModel( - name='Equipment', - ), - migrations.DeleteModel( - name='Lexicon', - ), - migrations.DeleteModel( - name='Owner', - ), - migrations.DeleteModel( - name='SampleLocation', - ), - migrations.DeleteModel( - name='Spring', - ), - migrations.DeleteModel( - name='Well', - ), - migrations.DeleteModel( - name='WellScreen', - ), - migrations.AddConstraint( - model_name='location_thing_junction', - constraint=models.UniqueConstraint(fields=('location', 'thing'), name='unique_location_thing'), - ), - ] diff --git a/geodjango/samplelocations/migrations/0003_remove_location_thing_junction_unique_location_thing_and_more.py b/geodjango/samplelocations/migrations/0003_remove_location_thing_junction_unique_location_thing_and_more.py deleted file mode 100644 index a9337d4..0000000 --- a/geodjango/samplelocations/migrations/0003_remove_location_thing_junction_unique_location_thing_and_more.py +++ /dev/null @@ -1,87 +0,0 @@ -# Generated by Django 5.2.3 on 2025-07-11 17:33 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('samplelocations', '0002_datastream_observation_location_sample_sensor_thing_and_more'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='location_thing_junction', - name='unique_location_thing', - ), - migrations.RenameField( - model_name='datastream', - old_name='thing', - new_name='thing_id', - ), - migrations.RenameField( - model_name='location_thing_junction', - old_name='location', - new_name='location_id', - ), - migrations.RenameField( - model_name='location_thing_junction', - old_name='thing', - new_name='thing_id', - ), - migrations.RenameField( - model_name='observation', - old_name='datastream', - new_name='datastream_id', - ), - migrations.RenameField( - model_name='sample', - old_name='thing', - new_name='thing_id', - ), - migrations.RenameField( - model_name='thing', - old_name='location', - new_name='location_id', - ), - migrations.RemoveField( - model_name='wellthing', - name='casing_depth', - ), - migrations.RemoveField( - model_name='wellthing', - name='casing_diameter', - ), - migrations.RemoveField( - model_name='wellthing', - name='hole_depth', - ), - migrations.RemoveField( - model_name='wellthing', - name='well_depth', - ), - migrations.AddField( - model_name='wellthing', - name='casing_depth_ft', - field=models.FloatField(blank=True, help_text='casing depth feet below ground surface', null=True), - ), - migrations.AddField( - model_name='wellthing', - name='casing_diameter_ft', - field=models.FloatField(blank=True, help_text='casing diameter in ft', null=True), - ), - migrations.AddField( - model_name='wellthing', - name='hole_depth_ft', - field=models.FloatField(blank=True, help_text='hole depth feet below ground surface', null=True), - ), - migrations.AddField( - model_name='wellthing', - name='well_depth_ft', - field=models.FloatField(blank=True, help_text='well depth feet below ground surface', null=True), - ), - migrations.AddConstraint( - model_name='location_thing_junction', - constraint=models.UniqueConstraint(fields=('location_id', 'thing_id'), name='unique_location_thing'), - ), - ] diff --git a/geodjango/samplelocations/migrations/0004_sensor_name.py b/geodjango/samplelocations/migrations/0004_sensor_name.py deleted file mode 100644 index 901f494..0000000 --- a/geodjango/samplelocations/migrations/0004_sensor_name.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.3 on 2025-07-11 18:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('samplelocations', '0003_remove_location_thing_junction_unique_location_thing_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='sensor', - name='name', - field=models.CharField(blank=True, max_length=100, null=True), - ), - ] diff --git a/geodjango/samplelocations/models.py b/geodjango/samplelocations/models.py index 13be40f..7b989ea 100644 --- a/geodjango/samplelocations/models.py +++ b/geodjango/samplelocations/models.py @@ -34,11 +34,24 @@ class Meta: #--------Thing model ----------- +# Define class-based choices for the 'thing_type' field. +# This allows for a more structured way to define and use choices in Django models. +# The format is CHOICE = " database value", "human-readable or display name" +class ThingType(models.TextChoices): + WELL = "W", "Well" + SPRING = "S", "Spring" class Thing(models.Model): """A base model representing a generic monitoring station (Thing)""" + thing_id = models.BigAutoField(primary_key=True) name = models.CharField(max_length=100, unique=True) + thing_type = models.CharField( + max_length=2, + choices=ThingType.choices, # Use the choices defined in the ThingType class. + default=ThingType.WELL, # Set a default value for the field. + verbose_name="type of thing" # Human-readable label for user interfaces like forms and admin panel. + ) release_status = models.BooleanField(default=False) date_created = models.DateTimeField(auto_now_add=True) # The 'location' field sets up the M:M relationship and specifies @@ -50,8 +63,20 @@ class Thing(models.Model): verbose_name= "related location" # Human-readable label for user interfaces like forms and the admin panel. ) + #Fields specific to a WELL + well_depth_ft = models.FloatField(blank=True, null=True, help_text="well depth feet below ground surface") + hole_depth_ft = models.FloatField(blank=True, null=True, help_text="hole depth feet below ground surface") + casing_diameter_ft = models.FloatField(blank=True, null=True, help_text="casing diameter in ft") + casing_depth_ft = models.FloatField(blank=True, null=True, help_text="casing depth feet below ground surface") + casing_description = models.CharField(max_length=50, blank=True, null=True) + construction_notes = models.TextField(blank=True, null=True) # Use TextField over CharField for long-form text of variable length without a predefined limit. + + #Fields specific to a SPRING + spring_type = models.CharField(max_length=255, blank=True, null=True) # e.g. "artesian", "subartesian", "thermal", etc. + + def __str__(self): - return f"Thing object with id {self.thing_id} and name {self.name}" + return f"Thing object is a {self.thing_type} with name {self.name}" class Meta: verbose_name = "Thing" @@ -93,51 +118,6 @@ class Meta: db_table_comment = "Junction table linking Location and Thing models" -#--------WellThing model. Inherits all fields from Thing model ----------- - -class WellThing(Thing): - """ A specific type of monitoring station (Thing) representing a well.""" - wellthing_id = models.BigAutoField(primary_key=True) - # This field creates the inheritance link from WellThing back to Thing. - # The name 'thing_ptr' is a conventional naming choice in Django for the parent link field, - thing_ptr= models.OneToOneField( - Thing, - on_delete=models.CASCADE, - parent_link = True, - related_name='wellthings', - verbose_name="related thing" - ) - well_depth_ft = models.FloatField(blank=True, null=True, help_text="well depth feet below ground surface") - hole_depth_ft = models.FloatField(blank=True, null=True, help_text="hole depth feet below ground surface") - casing_diameter_ft = models.FloatField(blank=True, null=True, help_text="casing diameter in ft") - casing_depth_ft = models.FloatField(blank=True, null=True, help_text="casing depth feet below ground surface") - casing_description = models.CharField(max_length=50, blank=True, null=True) - construction_notes = models.TextField(blank=True, null=True) # Use TextField over CharField for long-form text of variable length without a predefined limit. - - def __str__(self): - return f"{self.name} (Well)" - - -#--------SpringThing model. Inherits all fields from Thing model ----------- - -class SpringThing(Thing): - """ A specific type of monitoring station (Thing) representing a spring.""" - springthing_id = models.BigAutoField(primary_key=True) - # This field creates the inheritance link from SpringThing back to Thing. - # The name 'thing_ptr' is a conventional naming choice in Django for the parent link field, - thing_ptr = models.OneToOneField( - Thing, - on_delete=models.CASCADE, - parent_link=True, - related_name='springthings', - verbose_name="related thing" - ) - description = models.CharField(max_length=255, blank=True, null=True) - - def __str__(self): - return f"{self.name} (Spring)" - - #--------Sensor model----------- #TODO: add a 'name' field to this model. class Sensor(models.Model): @@ -168,11 +148,22 @@ def __str__(self): #--------Sample model----------- +# Define choices for thhe 'sample_matrix' field. +# The format is CHOICE = " database value", "human-readable or display name" +class SampleMatrix(models.TextChoices): + GROUNDWATER = "GW", "Groundwater" + SOIL = "S", "Soil" class Sample(models.Model): """Represents a sample collected from a Thing""" sample_id = models.BigAutoField(primary_key=True) thing_id = models.ForeignKey(Thing, on_delete=models.CASCADE, related_name="samples", verbose_name="related thing") + sample_matrix = models.CharField( + max_length=2, + choices=SampleMatrix.choices, # Use the choices defined in the SampleMatrix class + default=SampleMatrix.GROUNDWATER, # Set a default value for the field. + verbose_name="type of sample" # Human-readable label for user interfaces like forms and the admin panel. + ) sample_date = models.DateTimeField() sample_notes = models.TextField(blank=True, null=True)