Added view to get models by pk

This commit is contained in:
Johannes Randerath 2024-06-17 14:26:23 +02:00
parent 8f60efd87c
commit 26b08b72dd
6 changed files with 276 additions and 112 deletions

View File

@ -50,77 +50,7 @@ import datetime
import django.db.models import django.db.models
import time import time
from pt_map.gtfs_schema import gtfs_schema from pt_map.gtfs_schema import gtfs_schema
from.class_names import *
time_delta = int(datetime.datetime(2024,1,1).timestamp())
primary_keys = { pt_map.models.Agency: "agency_id",
pt_map.models.Level: "level_id",
pt_map.models.Stop: "stop_id",
pt_map.models.Route: "route_id",
pt_map.models.Shape: "shape_id",
pt_map.models.Calendar: "service_id",
pt_map.models.CalendarDate: None,
pt_map.models.Trip: "trip_id",
pt_map.models.LocationGroup: "location_group_id",
pt_map.models.LocationsGeojson: None,
pt_map.models.StopTime: None,
pt_map.models.FareAttribute: "fare_id",
pt_map.models.FareRule: None,
pt_map.models.Frequency: None,
pt_map.models.Transfer: None,
pt_map.models.Pathway: "pathway_id",
pt_map.models.FeedInfo: None,
pt_map.models.BookingRule: "booking_rule_id",
pt_map.models.Translation: None,
pt_map.models.Attribution: "attribution_id",
pt_map.models.LocationGroupStop: None,
pt_map.models.Network: "network_id",
pt_map.models.RouteNetwork: None,
pt_map.models.Area: None,
pt_map.models.StopArea: None,
pt_map.models.FareMedium: "fare_media_id",
pt_map.models.FareProduct: None,
pt_map.models.Timeframe: None,
pt_map.models.FareLegRule: None,
pt_map.models.FareTransferRule: None,
}
foreign_keys = [
(pt_map.models.Agency, []),
(pt_map.models.Level, []),
(pt_map.models.Stop, [(pt_map.models.Stop, 'parent_station'), (pt_map.models.Level, 'level_id'), ]),
(pt_map.models.Route, [(pt_map.models.Agency, 'agency_id'), ]),
(pt_map.models.Shape, []),
(pt_map.models.Calendar, []),
(pt_map.models.CalendarDate, []),
(pt_map.models.Trip, [(pt_map.models.Route, 'route_id'), (pt_map.models.Shape, 'shape_id'), ]),
(pt_map.models.LocationGroup, []),
(pt_map.models.LocationsGeojson, []),
(pt_map.models.StopTime, [(pt_map.models.Trip, 'trip_id'), (pt_map.models.Stop, 'stop_id'), (pt_map.models.LocationGroup, 'location_group_id'), (pt_map.models.LocationsGeojson, 'location_id'), ]),
(pt_map.models.FareAttribute, [(pt_map.models.Agency, 'agency_id'), ]),
(pt_map.models.FareRule, [(pt_map.models.FareAttribute, 'fare_id'), (pt_map.models.Route, 'route_id'), ]),
(pt_map.models.Frequency, [(pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.Transfer, [(pt_map.models.Stop, 'from_stop_id'), (pt_map.models.Stop, 'to_stop_id'), (pt_map.models.Route, 'from_route_id'), (pt_map.models.Route, 'to_route_id'), (pt_map.models.Trip, 'from_trip_id'), (pt_map.models.Trip, 'to_trip_id'), ]),
(pt_map.models.Pathway, [(pt_map.models.Stop, 'from_stop_id'), (pt_map.models.Stop, 'to_stop_id'), ]),
(pt_map.models.FeedInfo, []),
(pt_map.models.BookingRule, [(pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.Translation, []),
(pt_map.models.Attribution, [(pt_map.models.Agency, 'agency_id'), (pt_map.models.Route, 'route_id'), (pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.LocationGroupStop, [(pt_map.models.LocationGroup, 'location_group_id'), (pt_map.models.Stop, 'stop_id'), ]),
(pt_map.models.Network, []),
(pt_map.models.RouteNetwork, [(pt_map.models.Network, 'network_id'), (pt_map.models.Route, 'route_id'), ]),
(pt_map.models.Area, []),
(pt_map.models.StopArea, [(pt_map.models.Area, 'area_id'), (pt_map.models.Stop, 'stop_id'), ]),
(pt_map.models.FareMedium, []),
(pt_map.models.FareProduct, []),
(pt_map.models.Timeframe, []),
(pt_map.models.FareLegRule, [(pt_map.models.Network, 'network_id'), (pt_map.models.Area, 'from_area_id'), (pt_map.models.Area, 'to_area_id'), (pt_map.models.Timeframe, 'from_timeframe_group_id'), (pt_map.models.Timeframe, 'to_timeframe_group_id'), (pt_map.models.FareProduct, 'fare_product_id'), ]),
(pt_map.models.FareTransferRule, [(pt_map.models.FareProduct, 'fare_product_id'), ]),
]
class_names = {'Agency': 'agency', 'Stop': 'stops', 'Route': 'routes', 'Trip': 'trips', 'StopTime': 'stop_times', 'Calendar': 'calendar', 'CalendarDate': 'calendar_dates', 'FareAttribute': 'fare_attributes', 'FareRule': 'fare_rules', 'Timeframe': 'timeframes', 'FareMedium': 'fare_media', 'FareProduct': 'fare_products', 'FareLegRule': 'fare_leg_rules', 'FareTransferRule': 'fare_transfer_rules', 'Area': 'areas', 'StopArea': 'stop_areas', 'Network': 'networks', 'RouteNetwork': 'route_networks', 'Shape': 'shapes', 'Frequency': 'frequencies', 'Transfer': 'transfers', 'Pathway': 'pathways', 'Level': 'levels', 'LocationGroup': 'location_groups', 'LocationGroupStop': 'location_group_stops', 'LocationsGeojson': 'locations_geojson', 'BookingRule': 'booking_rules', 'Translation': 'translations', 'FeedInfo': 'feed_info', 'Attribution': 'attributions'}
def toCamelCase(s: str): def toCamelCase(s: str):
@ -275,38 +205,6 @@ def gtfs_to_db(g: pt_map.gtfs.GTFS):
m.objects.create(**defaults) m.objects.create(**defaults)
reversed_file_mapping = {
"Agency": "agency",
"Stop": "stops",
"Route": "routes",
"Trip": "trips",
"StopTime": "stop_times",
"Calendar": "calendar",
"CalendarDate": "calendar_dates",
"FareAttribute": "fare_attributes",
"FareRule": "fare_rules",
"Timeframe": "timeframes",
"FareMedium": "fare_media",
"FareProduct": "fare_products",
"FareLegRule": "fare_leg_rules",
"FareTransferRule": "fare_transfer_rules",
"Area": "areas",
"StopArea": "stop_areas",
"Network": "networks",
"RouteNetwork": "route_networks",
"Shape": "shapes",
"Frequency": "frequencies",
"Transfer": "transfers",
"Pathway": "pathways",
"Level": "levels",
"LocationGroup": "location_groups",
"LocationGroupStop": "location_group_stops",
"LocationsGeojson": "locations.geojson",
"BookingRule": "booking_rules",
"Translation": "translations",
"FeedInfo": "feed_info",
"Attribution": "attributions"
}
def db_to_gtfs(q: list[django.db.models.query.QuerySet], folder_path: str = ""): def db_to_gtfs(q: list[django.db.models.query.QuerySet], folder_path: str = ""):

View File

@ -3,6 +3,9 @@ Constant defining different variation of the file names in GTFS / our model name
""" """
import pt_map.models import pt_map.models
import datetime
time_delta = int(datetime.datetime(2024,1,1).timestamp())
class_names = [ class_names = [
{ {
@ -120,7 +123,7 @@ class_names = [
pt_map.models.StopArea: "stop_areas", pt_map.models.StopArea: "stop_areas",
pt_map.models.Network: "networks", pt_map.models.Network: "networks",
pt_map.models.RouteNetwork: "route_networks", pt_map.models.RouteNetwork: "route_networks",
pt_map.models.Shape: "shapes", pt_map.models.Shape: "shapes",
pt_map.models.Frequency: "frequencies", pt_map.models.Frequency: "frequencies",
pt_map.models.Transfer: "transfers", pt_map.models.Transfer: "transfers",
pt_map.models.Pathway: "pathways", pt_map.models.Pathway: "pathways",
@ -136,3 +139,123 @@ class_names = [
] ]
reversed_file_mapping = {
"Agency": "agency",
"Stop": "stops",
"Route": "routes",
"Trip": "trips",
"StopTime": "stop_times",
"Calendar": "calendar",
"CalendarDate": "calendar_dates",
"FareAttribute": "fare_attributes",
"FareRule": "fare_rules",
"Timeframe": "timeframes",
"FareMedium": "fare_media",
"FareProduct": "fare_products",
"FareLegRule": "fare_leg_rules",
"FareTransferRule": "fare_transfer_rules",
"Area": "areas",
"StopArea": "stop_areas",
"Network": "networks",
"RouteNetwork": "route_networks",
"Shape": "shapes",
"Frequency": "frequencies",
"Transfer": "transfers",
"Pathway": "pathways",
"Level": "levels",
"LocationGroup": "location_groups",
"LocationGroupStop": "location_group_stops",
"LocationsGeojson": "locations.geojson",
"BookingRule": "booking_rules",
"Translation": "translations",
"FeedInfo": "feed_info",
"Attribution": "attributions"
}
case_swap = {'Agency': 'agency', 'Stop': 'stops', 'Route': 'routes', 'Trip': 'trips', 'StopTime': 'stop_times', 'Calendar': 'calendar', 'CalendarDate': 'calendar_dates', 'FareAttribute': 'fare_attributes', 'FareRule': 'fare_rules', 'Timeframe': 'timeframes', 'FareMedium': 'fare_media', 'FareProduct': 'fare_products', 'FareLegRule': 'fare_leg_rules', 'FareTransferRule': 'fare_transfer_rules', 'Area': 'areas', 'StopArea': 'stop_areas', 'Network': 'networks', 'RouteNetwork': 'route_networks', 'Shape': 'shapes', 'Frequency': 'frequencies', 'Transfer': 'transfers', 'Pathway': 'pathways', 'Level': 'levels', 'LocationGroup': 'location_groups', 'LocationGroupStop': 'location_group_stops', 'LocationsGeojson': 'locations_geojson', 'BookingRule': 'booking_rules', 'Translation': 'translations', 'FeedInfo': 'feed_info', 'Attribution': 'attributions'}
primary_keys = { pt_map.models.Agency: "agency_id",
pt_map.models.Level: "level_id",
pt_map.models.Stop: "stop_id",
pt_map.models.Route: "route_id",
pt_map.models.Shape: "shape_id",
pt_map.models.Calendar: "service_id",
pt_map.models.CalendarDate: None,
pt_map.models.Trip: "trip_id",
pt_map.models.LocationGroup: "location_group_id",
pt_map.models.LocationsGeojson: None,
pt_map.models.StopTime: None,
pt_map.models.FareAttribute: "fare_id",
pt_map.models.FareRule: None,
pt_map.models.Frequency: None,
pt_map.models.Transfer: None,
pt_map.models.Pathway: "pathway_id",
pt_map.models.FeedInfo: None,
pt_map.models.BookingRule: "booking_rule_id",
pt_map.models.Translation: None,
pt_map.models.Attribution: "attribution_id",
pt_map.models.LocationGroupStop: None,
pt_map.models.Network: "network_id",
pt_map.models.RouteNetwork: None,
pt_map.models.Area: None,
pt_map.models.StopArea: None,
pt_map.models.FareMedium: "fare_media_id",
pt_map.models.FareProduct: None,
pt_map.models.Timeframe: None,
pt_map.models.FareLegRule: None,
pt_map.models.FareTransferRule: None,
}
classes_by_primary_keys = { "agency_id": pt_map.models.Agency,
"level_id": pt_map.models.Level,
"stop_id": pt_map.models.Stop,
"route_id": pt_map.models.Route,
"shape_id": pt_map.models.Shape,
"service_id": pt_map.models.Calendar,
"trip_id": pt_map.models.Trip,
"location_group_id": pt_map.models.LocationGroup,
"fare_id": pt_map.models.FareAttribute,
"pathway_id": pt_map.models.Pathway,
"booking_rule_id": pt_map.models.BookingRule,
"attribution_id": pt_map.models.Attribution,
"network_id": pt_map.models.Network,
"fare_media_id": pt_map.models.FareMedium,
}
foreign_keys = [
(pt_map.models.Agency, []),
(pt_map.models.Level, []),
(pt_map.models.Stop, [(pt_map.models.Stop, 'parent_station'), (pt_map.models.Level, 'level_id'), ]),
(pt_map.models.Route, [(pt_map.models.Agency, 'agency_id'), ]),
(pt_map.models.Shape, []),
(pt_map.models.Calendar, []),
(pt_map.models.CalendarDate, []),
(pt_map.models.Trip, [(pt_map.models.Route, 'route_id'), (pt_map.models.Shape, 'shape_id'), ]),
(pt_map.models.LocationGroup, []),
(pt_map.models.LocationsGeojson, []),
(pt_map.models.StopTime, [(pt_map.models.Trip, 'trip_id'), (pt_map.models.Stop, 'stop_id'), (pt_map.models.LocationGroup, 'location_group_id'), (pt_map.models.LocationsGeojson, 'location_id'), ]),
(pt_map.models.FareAttribute, [(pt_map.models.Agency, 'agency_id'), ]),
(pt_map.models.FareRule, [(pt_map.models.FareAttribute, 'fare_id'), (pt_map.models.Route, 'route_id'), ]),
(pt_map.models.Frequency, [(pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.Transfer, [(pt_map.models.Stop, 'from_stop_id'), (pt_map.models.Stop, 'to_stop_id'), (pt_map.models.Route, 'from_route_id'), (pt_map.models.Route, 'to_route_id'), (pt_map.models.Trip, 'from_trip_id'), (pt_map.models.Trip, 'to_trip_id'), ]),
(pt_map.models.Pathway, [(pt_map.models.Stop, 'from_stop_id'), (pt_map.models.Stop, 'to_stop_id'), ]),
(pt_map.models.FeedInfo, []),
(pt_map.models.BookingRule, [(pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.Translation, []),
(pt_map.models.Attribution, [(pt_map.models.Agency, 'agency_id'), (pt_map.models.Route, 'route_id'), (pt_map.models.Trip, 'trip_id'), ]),
(pt_map.models.LocationGroupStop, [(pt_map.models.LocationGroup, 'location_group_id'), (pt_map.models.Stop, 'stop_id'), ]),
(pt_map.models.Network, []),
(pt_map.models.RouteNetwork, [(pt_map.models.Network, 'network_id'), (pt_map.models.Route, 'route_id'), ]),
(pt_map.models.Area, []),
(pt_map.models.StopArea, [(pt_map.models.Area, 'area_id'), (pt_map.models.Stop, 'stop_id'), ]),
(pt_map.models.FareMedium, []),
(pt_map.models.FareProduct, []),
(pt_map.models.Timeframe, []),
(pt_map.models.FareLegRule, [(pt_map.models.Network, 'network_id'), (pt_map.models.Area, 'from_area_id'), (pt_map.models.Area, 'to_area_id'), (pt_map.models.Timeframe, 'from_timeframe_group_id'), (pt_map.models.Timeframe, 'to_timeframe_group_id'), (pt_map.models.FareProduct, 'fare_product_id'), ]),
(pt_map.models.FareTransferRule, [(pt_map.models.FareProduct, 'fare_product_id'), ]),
]
fk_dict = {fk[0]: fk[1] for fk in foreign_keys}

View File

@ -3,3 +3,5 @@ from django import forms
class Form1(forms.Form): class Form1(forms.Form):
title = forms.CharField(max_length=255) title = forms.CharField(max_length=255)
file = forms.FileField() file = forms.FileField()

View File

@ -25,6 +25,7 @@ class Agency(models.Model):
agency_phone = models.CharField(max_length=50, blank=True, null=True) agency_phone = models.CharField(max_length=50, blank=True, null=True)
agency_fare_url = models.URLField(blank=True, null=True) agency_fare_url = models.URLField(blank=True, null=True)
agency_email = models.EmailField(blank=True, null=True) agency_email = models.EmailField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Level(models.Model): class Level(models.Model):
""" """
@ -33,6 +34,7 @@ class Level(models.Model):
level_id = models.CharField(max_length=255, primary_key=True) level_id = models.CharField(max_length=255, primary_key=True)
level_index = models.FloatField() level_index = models.FloatField()
level_name = models.CharField(max_length=255, blank=True, null=True) level_name = models.CharField(max_length=255, blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Stop(models.Model): class Stop(models.Model):
""" """
@ -52,6 +54,7 @@ class Stop(models.Model):
wheelchair_boarding = models.IntegerField(blank=True, null=True) wheelchair_boarding = models.IntegerField(blank=True, null=True)
level_id = models.ForeignKey(Level, on_delete=models.SET_NULL, blank=True, null=True) level_id = models.ForeignKey(Level, on_delete=models.SET_NULL, blank=True, null=True)
platform_code = models.CharField(max_length=50, blank=True, null=True) platform_code = models.CharField(max_length=50, blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Route(models.Model): class Route(models.Model):
""" """
@ -69,6 +72,7 @@ class Route(models.Model):
route_sort_order = models.IntegerField(blank=True, null=True) route_sort_order = models.IntegerField(blank=True, null=True)
continuous_pickup = models.IntegerField(blank=True, null=True) continuous_pickup = models.IntegerField(blank=True, null=True)
continuous_drop_off = models.IntegerField(blank=True, null=True) continuous_drop_off = models.IntegerField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Shape(models.Model): class Shape(models.Model):
""" """
@ -79,6 +83,7 @@ class Shape(models.Model):
shape_pt_lon = models.FloatField() shape_pt_lon = models.FloatField()
shape_pt_sequence = models.IntegerField() shape_pt_sequence = models.IntegerField()
shape_dist_traveled = models.FloatField(blank=True, null=True) shape_dist_traveled = models.FloatField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Meta: class Meta:
unique_together = (('shape_id', 'shape_pt_sequence'),) unique_together = (('shape_id', 'shape_pt_sequence'),)
@ -87,6 +92,7 @@ class Calendar(models.Model):
""" """
Represents calendar.txt from the GTFS Reference. Represents calendar.txt from the GTFS Reference.
""" """
calendar_id = models.BigAutoField(primary_key=True)
service_id = models.CharField(max_length=255,primary_key=True) service_id = models.CharField(max_length=255,primary_key=True)
monday = models.BooleanField() monday = models.BooleanField()
tuesday = models.BooleanField() tuesday = models.BooleanField()
@ -97,14 +103,17 @@ class Calendar(models.Model):
sunday = models.BooleanField() sunday = models.BooleanField()
start_date = models.DateField() start_date = models.DateField()
end_date = models.DateField() end_date = models.DateField()
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class CalendarDate(models.Model): class CalendarDate(models.Model):
""" """
Represents calendar_date.txt from the GTFS Reference. Represents calendar_date.txt from the GTFS Reference.
""" """
calendar_date_id = models.BigAutoField(primary_key=True)
service_id = models.CharField(max_length=255) service_id = models.CharField(max_length=255)
date = models.DateField() date = models.DateField()
exception_type = models.IntegerField() exception_type = models.IntegerField()
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Meta: class Meta:
unique_together = (('service_id', 'date'),) unique_together = (('service_id', 'date'),)
@ -137,6 +146,7 @@ class Trip(models.Model):
"wheelchair_accessible": self.wheelchair_accessible, "wheelchair_accessible": self.wheelchair_accessible,
"bikes_allowed": self.bikes_allowed, "bikes_allowed": self.bikes_allowed,
} }
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class LocationGroup(models.Model): class LocationGroup(models.Model):
""" """
@ -145,6 +155,7 @@ class LocationGroup(models.Model):
location_group_id = models.CharField(max_length=255, primary_key=True) location_group_id = models.CharField(max_length=255, primary_key=True)
location_group_name = models.CharField(max_length=255) location_group_name = models.CharField(max_length=255)
location_group_type = models.CharField(max_length=255) location_group_type = models.CharField(max_length=255)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class LocationsGeojson(models.Model): class LocationsGeojson(models.Model):
""" """
@ -157,11 +168,13 @@ class LocationsGeojson(models.Model):
location_type = models.CharField(max_length=255) location_type = models.CharField(max_length=255)
parent_location_id = models.CharField(max_length=255, blank=True, null=True) parent_location_id = models.CharField(max_length=255, blank=True, null=True)
wheelchair_boarding = models.BooleanField(blank=True, null=True) wheelchair_boarding = models.BooleanField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class StopTime(models.Model): class StopTime(models.Model):
""" """
Represents stop_time.txt from the GTFS Reference. Represents stop_time.txt from the GTFS Reference.
""" """
stop_time_id = models.BigAutoField(primary_key=True)
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE) trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
arrival_time = models.TimeField(blank=True, null=True) arrival_time = models.TimeField(blank=True, null=True)
departure_time = models.TimeField(blank=True, null=True) departure_time = models.TimeField(blank=True, null=True)
@ -174,6 +187,7 @@ class StopTime(models.Model):
drop_off_type = models.IntegerField(blank=True, null=True) drop_off_type = models.IntegerField(blank=True, null=True)
shape_dist_traveled = models.FloatField(blank=True, null=True) shape_dist_traveled = models.FloatField(blank=True, null=True)
timepoint = models.IntegerField(blank=True, null=True) timepoint = models.IntegerField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Meta: class Meta:
unique_together = (('trip_id', 'stop_sequence'),) unique_together = (('trip_id', 'stop_sequence'),)
@ -189,6 +203,7 @@ class FareAttribute(models.Model):
transfers = models.IntegerField() transfers = models.IntegerField()
agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True) agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
transfer_duration = models.IntegerField(blank=True, null=True) transfer_duration = models.IntegerField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FareRule(models.Model): class FareRule(models.Model):
""" """
@ -199,6 +214,7 @@ class FareRule(models.Model):
origin_id = models.IntegerField(blank=True, null=True) origin_id = models.IntegerField(blank=True, null=True)
destination_id = models.CharField(max_length=255, blank=True, null=True) destination_id = models.CharField(max_length=255, blank=True, null=True)
contains_id = models.CharField(max_length=255, blank=True, null=True) contains_id = models.CharField(max_length=255, blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Frequency(models.Model): class Frequency(models.Model):
""" """
@ -209,6 +225,7 @@ class Frequency(models.Model):
end_time = models.TimeField() end_time = models.TimeField()
headway_secs = models.IntegerField() headway_secs = models.IntegerField()
exact_times = models.IntegerField(blank=True, null=True) exact_times = models.IntegerField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Transfer(models.Model): class Transfer(models.Model):
""" """
@ -222,6 +239,7 @@ class Transfer(models.Model):
to_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_trip') to_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_trip')
transfer_type = models.IntegerField() transfer_type = models.IntegerField()
min_transfer_time = models.IntegerField(blank=True, null=True) min_transfer_time = models.IntegerField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Meta: class Meta:
unique_together = (('from_stop_id', 'to_stop_id'),) unique_together = (('from_stop_id', 'to_stop_id'),)
@ -242,11 +260,13 @@ class Pathway(models.Model):
min_width = models.FloatField(blank=True, null=True) min_width = models.FloatField(blank=True, null=True)
signposted_as = models.CharField(max_length=255, blank=True, null=True) signposted_as = models.CharField(max_length=255, blank=True, null=True)
reversed_signposted_as = models.CharField(max_length=255, blank=True, null=True) reversed_signposted_as = models.CharField(max_length=255, blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FeedInfo(models.Model): class FeedInfo(models.Model):
""" """
Represents feed_info.txt from the GTFS Reference. Represents feed_info.txt from the GTFS Reference.
""" """
feed_info_id = models.BigAutoField(primary_key=True)
feed_publisher_name = models.CharField(max_length=255) feed_publisher_name = models.CharField(max_length=255)
feed_publisher_url = models.URLField() feed_publisher_url = models.URLField()
feed_lang = models.CharField(max_length=255) feed_lang = models.CharField(max_length=255)
@ -257,6 +277,7 @@ class FeedInfo(models.Model):
feed_contact_email = models.EmailField(blank=True, null=True) feed_contact_email = models.EmailField(blank=True, null=True)
feed_contact_url = models.URLField(blank=True, null=True) feed_contact_url = models.URLField(blank=True, null=True)
feed_id = models.BigAutoField(primary_key=True) feed_id = models.BigAutoField(primary_key=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class BookingRule(models.Model): class BookingRule(models.Model):
""" """
@ -269,6 +290,7 @@ class BookingRule(models.Model):
booking_type = models.CharField(max_length=255) booking_type = models.CharField(max_length=255)
rule_criteria = models.TextField(blank=True, null=True) rule_criteria = models.TextField(blank=True, null=True)
booking_rule_instructions = models.TextField(blank=True, null=True) booking_rule_instructions = models.TextField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Translation(models.Model): class Translation(models.Model):
""" """
@ -278,6 +300,7 @@ class Translation(models.Model):
field_name = models.CharField(max_length=255) field_name = models.CharField(max_length=255)
language = models.CharField(max_length=2) language = models.CharField(max_length=2)
translation = models.TextField() translation = models.TextField()
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Attribution(models.Model): class Attribution(models.Model):
""" """
@ -291,6 +314,7 @@ class Attribution(models.Model):
attribution_url = models.URLField() attribution_url = models.URLField()
attribution_email = models.EmailField(blank=True, null=True) attribution_email = models.EmailField(blank=True, null=True)
attribution_phone = models.CharField(max_length=50, blank=True, null=True) attribution_phone = models.CharField(max_length=50, blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class LocationGroupStop(models.Model): class LocationGroupStop(models.Model):
""" """
@ -298,6 +322,7 @@ class LocationGroupStop(models.Model):
""" """
location_group_id = models.ForeignKey(LocationGroup, on_delete=models.CASCADE) location_group_id = models.ForeignKey(LocationGroup, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE) stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Network(models.Model): class Network(models.Model):
""" """
@ -305,6 +330,7 @@ class Network(models.Model):
""" """
network_id = models.CharField(max_length=255, primary_key=True) network_id = models.CharField(max_length=255, primary_key=True)
network_name = models.CharField(max_length=255) network_name = models.CharField(max_length=255)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class RouteNetwork(models.Model): class RouteNetwork(models.Model):
""" """
@ -314,6 +340,7 @@ class RouteNetwork(models.Model):
route_network_name = models.CharField(max_length=255) route_network_name = models.CharField(max_length=255)
network_id = models.ForeignKey(Network, on_delete=models.CASCADE) network_id = models.ForeignKey(Network, on_delete=models.CASCADE)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE) route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Area(models.Model): class Area(models.Model):
""" """
@ -322,6 +349,7 @@ class Area(models.Model):
area_id = models.CharField(max_length=255, primary_key=True) area_id = models.CharField(max_length=255, primary_key=True)
area_name = models.CharField(max_length=255) area_name = models.CharField(max_length=255)
area_description = models.TextField(blank=True, null=True) area_description = models.TextField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class StopArea(models.Model): class StopArea(models.Model):
""" """
@ -332,6 +360,7 @@ class StopArea(models.Model):
stop_area_description = models.TextField(blank=True, null=True) stop_area_description = models.TextField(blank=True, null=True)
area_id = models.ForeignKey(Area, on_delete=models.CASCADE) area_id = models.ForeignKey(Area, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE) stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FareMedium(models.Model): class FareMedium(models.Model):
""" """
@ -340,6 +369,7 @@ class FareMedium(models.Model):
fare_media_id = models.CharField(max_length=255, primary_key=True) fare_media_id = models.CharField(max_length=255, primary_key=True)
fare_media_name = models.CharField(max_length=255) fare_media_name = models.CharField(max_length=255)
fare_media_description = models.TextField(blank=True, null=True) fare_media_description = models.TextField(blank=True, null=True)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FareProduct(models.Model): class FareProduct(models.Model):
""" """
@ -350,6 +380,7 @@ class FareProduct(models.Model):
fare_product_description = models.TextField(blank=True, null=True) fare_product_description = models.TextField(blank=True, null=True)
amount = models.FloatField() amount = models.FloatField()
curreny = models.CharField(max_length=64) curreny = models.CharField(max_length=64)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class Timeframe(models.Model): class Timeframe(models.Model):
""" """
@ -361,6 +392,7 @@ class Timeframe(models.Model):
end_date = models.DateField() end_date = models.DateField()
start_time = models.TimeField() start_time = models.TimeField()
end_time = models.TimeField() end_time = models.TimeField()
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FareLegRule(models.Model): class FareLegRule(models.Model):
""" """
@ -375,6 +407,7 @@ class FareLegRule(models.Model):
from_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_timeframe') from_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_timeframe')
to_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_timeframe') to_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_timeframe')
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.CASCADE) fare_product_id = models.ForeignKey(FareProduct, on_delete=models.CASCADE)
feed_info_id = models.ForeignKey(Feed_Info, on_delete=models.CASCADE, blank=True, null=True)
class FareTransferRule(models.Model): class FareTransferRule(models.Model):
""" """
@ -388,4 +421,3 @@ class FareTransferRule(models.Model):
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.SET_NULL, blank=True, null=True) fare_product_id = models.ForeignKey(FareProduct, on_delete=models.SET_NULL, blank=True, null=True)

View File

@ -7,4 +7,6 @@ from . import views
urlpatterns = [ urlpatterns = [
path("", views.index, name="index"), path("", views.index, name="index"),
path("data/", views.data, name="data"),
path("timetable/", views.timetable, name="timetable")
] ]

View File

@ -9,13 +9,16 @@ index(request)
Home page Home page
""" """
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse, HttpRequest from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpRequest
from django.core.exceptions import BadRequest, ObjectDoesNotExist
from .models import * from .models import *
from .forms import * from .forms import *
import json import json
from datetime import datetime from datetime import datetime
from django.views.decorators.csrf import csrf_exempt
from .class_names import *
def get_timetable(r, trips, stop_sequences): def get_timetable(r, trips_r, stop_sequence):
""" """
Given a pt_map.models.Route, calculate the timetable for all its stops. Given a pt_map.models.Route, calculate the timetable for all its stops.
@ -37,18 +40,17 @@ def get_timetable(r, trips, stop_sequences):
"stop_times" : dict(str, list(str)) "stop_times" : dict(str, list(str))
dict mapping stop_ids from stop_sequence to time strings the route is serving the stop at dict mapping stop_ids from stop_sequence to time strings the route is serving the stop at
""" """
timetable = {"stop_sequence": stop_sequences[r.route_id]} timetable = {"stop_sequence": stop_sequence}
sts = {} sts = {}
for stop in stop_sequences[r.route_id]: for stop in stop_sequence:
times = [] times = []
for t in trips[r.route_id]: for t in trips_r:
for st in StopTime.objects.filter(trip_id=t.trip_id): for st in StopTime.objects.filter(trip_id=t.trip_id):
times.append(st.departure_time.strftime("%H:%M")) times.append(st.departure_time.strftime("%H:%M"))
sts[stop] = times sts[stop] = times
timetable["stop_times"] = sts timetable["stop_times"] = sts
return timetable return timetable
def index(request): def index(request):
stops = {s.stop_id: {name: getattr(s, name) for name in ['stop_name', 'stop_lat', 'stop_lon']} for s in Stop.objects.all()} stops = {s.stop_id: {name: getattr(s, name) for name in ['stop_name', 'stop_lat', 'stop_lon']} for s in Stop.objects.all()}
route_name = lambda r : r.route_short_name if r.route_short_name else r.route_long_name route_name = lambda r : r.route_short_name if r.route_short_name else r.route_long_name
@ -65,9 +67,114 @@ def index(request):
if request.GET.get("timetable"): if request.GET.get("timetable"):
try: try:
r = Route.objects.get(route_id=request.GET.get("timetable")) r = Route.objects.get(route_id=request.GET.get("timetable"))
timetable = get_timetable(r, trips, stop_sequences) timetable = get_timetable(r, trips[r.route_id], stop_sequences[r.route_id])
except Route.DoesNotExist: except Route.DoesNotExist:
print(f"Invalid request for Route with id {request.GET['timetable']}") print(f"Invalid request for Route with id {request.GET['timetable']}")
context = {"stops": json.dumps(stops), "routes": json.dumps(routes), "timetable": json.dumps(timetable)} context = {"stops": json.dumps(stops), "routes": json.dumps(routes), "timetable": json.dumps(timetable)}
return render(request,"map.html", context) return render(request,"map.html", context)
def get_field_names(model: models.Model):
return [field.name for field in model._meta.fields]
def timetable(request):
if request.method == "GET":
try:
r = Route.objects.get(route_id=request.GET["route_id"])
trips_r = [t for t in Trip.objects.filter(route_id_id=r.route_id)]
stop_sequence = [s.stop_id.stop_id for s in sorted([s for s in StopTime.objects.filter(trip_id_id__exact=trips_r[0].trip_id)], key=lambda st : st.stop_sequence)]
timetable = get_timetable(r, trips_r, stop_sequence)
return HttpResponse(json.dumps(timetable), content_type="text/json")
except KeyError:
return HttpResponseBadRequest("route_id missing or malformed.")
except Route.DoesNotExist:
return HttpResponseBadRequest("Route not found.")
return HttpResponseNotAllowed(["GET"])
def get_pks_from_get(req_get):
result = {}
for k in req_get.keys():
if k in classes_by_primary_keys.keys():
result[classes_by_primary_keys[k]] = req_get.getlist(k)
return result
def get_obj_by_pk(mdl: models.Model, pks: list[str]):
return [obj for obj in [mdl.objects.get(**{primary_keys[mdl]: pk}) for pk in pks] if obj]
def obj_from_get(req_get) -> str:
return {mdl: get_obj_by_pk(mdl, keys) for mdl, keys in get_pks_from_get(req_get)}
def mdl_to_jsnzbl_dict(cls, obj: models.Model) -> dict:
result = {}
fields = get_field_names(cls)
for fk in fk_dict[cls]:
fields.remove(fk[1])
if getattr(obj, fk[1]):
result[fk[1]] = getattr(getattr(obj, fk[1]), primary_keys[fk[0]])
for field in fields:
if getattr(obj, field):
result[field] = getattr(obj, field)
return result
def json_from_pk(req_get) -> str:
for cpk in classes_by_primary_keys:
if req_get.get(cpk):
for key in (req_get[cpk] if isinstance(req_get[cpk], list) else [req_get[cpk]]):
obj = classes_by_primary_keys[cpk].objects.get(**{cpk: key})
for field in get_field_names(obj):
v = getattr(obj, field)
if v:
if field in [f[1] for f in foreign_keys[classes_by_primary_keys[cpk]]]:
fk = get_attr(v, field)
return json.dumps(obj)
def jsnzbl_from_get(req_get) -> str:
return {mdl._meta.object_name: [mdl_to_jsnzbl_dict(mdl, o) for o in get_obj_by_pk(mdl, keys)] for mdl, keys in get_pks_from_get(req_get).items()}
def jsnz(jsnzbl: dict):
return json.dumps(jsnzbl)
def rsp_for_json_from_get(req_get):
try:
return HttpResponse(jsnz(jsnzbl_from_get(req_get)))
except ObjectDoesNotExist:
return HttpResponseBadRequest("Object(s) not found.")
def data(request):
"""
Handle database requests from the frontend. Using Http semantics to specify what to do with the data.
Request
-------
PUT
Create a new object if no object with the given primary key exists in the database or delete and replace an existing object.
Body must be a json dict of lists of fully specified, valid models.
If primary keys are given as GET keys, they are applied to the first elements in their corresponding object lists. Primary keys in body will be ignored.
RETURN 400 if primary keys not existing.
PATCH
Modify an existing objects given the instructions in the body.
Body must be a json dict of lists of fields to change and their valid values existing objects in the database, identified by their valid primary keys as GET keys.
Primary keys in body will be ignored.
GET
Return json of models identified by primary keys.
DELETE
Delete models with given primary keys if they exist. Returns number of deleted models.
"""
if request.method == "PUT":
if not request.META["CONTENT_TYPE"] == 'application/json':
HttpResponseBadRequest('Request must be JSON.')
bdy = json.loads(request.body)
try:
obj = obj_from_get(request.GET)
except ObjectDoesNotExist:
return HttpResponseBadRequest("Did not find models corresponding to given pks.")
return HttpResponse(f"received {obj}")
elif request.method == "PATCH":
if not request.META["CONTENT_TYPE"] == 'application/json':
HttpResponseBadRequest('Request must be JSON.')
return HttpResponse(f"received {obj}")
elif request.method == "GET":
return rsp_for_json_from_get(request.GET)
return HttpResponseNotAllowed(['PUT', 'PATCH', 'GET'])