Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

27 create db tables aka django modelspy #50

Merged
merged 16 commits into from
May 3, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion app/route_rangers_api/models.py
Original file line number Diff line number Diff line change
@@ -1 +1,91 @@
from django.db import models
from django.contrib.gis.db import models

# from django.db import models

##TODO: Update function that can extract the census tract from the location
## using the Census API


def get_census_tract(location) -> str:
pass


#################################
######## TRANSIT MODELS #########
#################################


class Demographics(models.Model):
census_tract = models.CharField(
max_length=15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember @benjaleivas was ingesting at the block level, so as long as he is good with aggregating to the tract level by the time it goes to the db and that wont lose info for the frontend needs (I am pretty sure this is ok but want to double check)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified to the block level

) # Check length of census tract if its uniform to enforce it here
state = models.CharField(
max_length=15
) # Check if it's worth to keep or if we should add a method
county = models.CharField(max_length=15) # Same as above
population = models.IntegerField()
# age = models.IntegerField()
median_income = models.IntegerField()
transportation_to_work = models.CharField(
verbose_name="Means of Transportation to Work"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max chars?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing it!

)
work_commute_time = models.FloatField(verbose_name="Time of commuto to work")
vehicles_available = models.IntegerField()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would help at some point maybe from @benjaleivas to clarify the units commute in min? hour?

disability_status = models.IntegerField() # Check the type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this be a float median/mean estimate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this field is a count of vehicles


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe an enum? disabled, not disabled, temporarily disabled?


class TransitStation(models.Model):
station_id = models.CharField(max_length=30, primary_key=True)
location = models.PointField()
route = models.CharField(max_length=30)
census_tract = models.CharField(max_length=30, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a route name (like "Red Line") or route_id like "Chicago_CTA_R" or whatever it ends up being? Given that it's set up way, I take it we went with separate entities for each line for a multi-line stop

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think multiple routes have the same station_id (if we go along with the Roosevelt chat we had) so route or route_id would also need to be set as a primary key


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a foreign key to the census tract?

def get_census_tract(self):
self.census_tract = get_census_tract(self.location)


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For @jamesturk and @divij-sinha we decided to go with these RidershipRoute and RidershipStation tables because we realized that depending on the city the ridership metrics may occur at different levels (i.e. I think Portland may have route level ridership for the subway lines whereas the other cities have them at the station level).

For now it seems like we will have to create one view for Portland ridership and one view for Chicago/NYC ridership since they will pull from different tables so if you suggest handling this differently, i.e. add a city column and mode to each table or an association table please advise!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JPMartinezClaeys depending on the response to this question, the TransitModes might need to be accessible by Ridership instead of nested within TransitRoute

class TransitRidership(models.Model):
station = models.CharField(max_length=30)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this table needs a primary key (id or station/date combination) and foreign key to station_id so this table can be joined easily

date = models.DateField()
ridership = models.IntegerField()


class BikeStation(models.Model):
station_id = models.CharField(max_length=30, primary_key=True)
location = models.PointField()
census_tract = models.CharField(max_length=30, null=True)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foreign key

def get_census_tract(self):
self.census_tract = get_census_tract(self.location)


class BikeRidership(models.Model):
station = models.ForeignKey(BikeStation, on_delete=models.PROTECT)
date = models.DateField()
n_started = models.IntegerField()
n_ended = models.IntegerField()


#################################
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you JP! This looks great, the models are consistent with what we were expecting based on the documentation.

######## SURVEY MODELS ##########
#################################

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small note, these would typically be in their own app when they are this distinct. not necessary for the project, but wanted to mention as a "best practice"


class Survey(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateTimeField("Created at", auto_now_add=True)
questionnaire = models.JSONField()


class SurveyAnswer(models.Model):
user_id = models.CharField(max_length=30)
response_date = models.DateTimeField("Survey response date", auto_now_add=True)
city = models.CharField(max_length=30)
survey = models.ForeignKey(Survey, on_delete=models.PROTECT)
answers = models.JSONField()


class PlannedRoute(models.Model):
user_id = models.CharField(max_length=30)
response_date = models.DateTimeField("Survey response date", auto_now_add=True)
route = models.JSONField()
Loading