Passing stops and routes to index

This commit is contained in:
Johannes Randerath 2024-06-11 17:20:25 +02:00
parent 4028f63624
commit a310152c4f
20 changed files with 1345 additions and 667 deletions

View File

@ -2,5 +2,25 @@
### Tool for cities to easily publish their public transport in a standardized form
Public transport is often provided by many, smaller companies, operating mostly in their respective regions. A problem deriving from this is that, on a interregional, national and international, few machine-readable data is available. This impacts customers, as it makes it more difficult to find public transport routes, more so while travelling in regions they are less familiar with.
We designed a tool to provide city officials or volunteers to map the public transport in their jurisdiction using an easy-to-use graphical utility.
We designed a tool to provide city officials or volunteers to map the public transport in their jurisdiction using an easy-to-use graphical utility. https://www.gnu.org/software/make/
## Installation instructions
### Dependencies
First, make sure to have all dependencies installed:
- An up-to-date version of [Python](https://www.python.org/) and pip.
- The project's Python dependencies. We strongly recommend using a virtual environment and install the dependencies using `pip install -r requirements.txt` in the project's root directory.
- An up-to-date version of [Mariadb](https://mariadb.com/downloads/)
- If you want to build the documentation, you will need [Sphinx](https://www.sphinx-doc.org/en/master/) and [Make](https://www.gnu.org/software/make/)
### Database
- The database can be installed using `sudo mariadb -u root < setup_db.sql`
- The migrations should be applied using `python transport_accessibility/manage.py migrate`
- If you are having database problems and where using an old version of the database before, try resetting the database by issuing `sudo mariadb -u root < delete_db.sql && sudo mariadb -u root < setup_db.sql`, as we changed the character encoding in one of the earlier commits.
### Load example data
- Download some real or sample GTFS data from the Internet.
- Open a django shell: `python transport_accessibility/manage.py shell`
- Import the database bridging functions: `import pt_map.gtfs, pt_map.bridge`
- Load sample data to db: `pt_map.bridge.gtfs_to_db(pt_map.gtfs.GTFS("/path/to/folder"))` (This might take some time)

View File

@ -0,0 +1,447 @@
<?xml version="1.0" encoding="utf-8"?>
<gaphor xmlns="http://gaphor.sourceforge.net/model" version="3.0" gaphor-version="2.25.1">
<StyleSheet id="58d6989a-66f8-11ec-b4c8-0456e5e540ed">
<styleSheet>
<val>diagram {
/* line-style: sloppy 0.3; */
}
controlflow {
dash-style: 0;
}
</val>
</styleSheet>
</StyleSheet>
<Package id="58d6c2e8-66f8-11ec-b4c8-0456e5e540ed">
<name>
<val>Query</val>
</name>
<nestedPackage>
<reflist>
<ref refid="a021290e-71b1-11ec-a409-f47b099bf663"/>
<ref refid="c254a76c-71b1-11ec-a409-f47b099bf663"/>
<ref refid="cccf183a-71b1-11ec-a409-f47b099bf663"/>
<ref refid="f3a82730-71b1-11ec-a409-f47b099bf663"/>
</reflist>
</nestedPackage>
</Package>
<Package id="a021290e-71b1-11ec-a409-f47b099bf663">
<name>
<val>1. Use Cases</val>
</name>
<ownedDiagram>
<reflist>
<ref refid="0c81912e-71b2-11ec-a409-f47b099bf663"/>
<ref refid="3132c19a-71b3-11ec-a409-f47b099bf663"/>
</reflist>
</ownedDiagram>
<package>
<ref refid="58d6c2e8-66f8-11ec-b4c8-0456e5e540ed"/>
</package>
</Package>
<Package id="c254a76c-71b1-11ec-a409-f47b099bf663">
<name>
<val>2. Domain Analysis</val>
</name>
<ownedDiagram>
<reflist>
<ref refid="06ecc092-71b4-11ec-a409-f47b099bf663"/>
</reflist>
</ownedDiagram>
<package>
<ref refid="58d6c2e8-66f8-11ec-b4c8-0456e5e540ed"/>
</package>
</Package>
<Package id="cccf183a-71b1-11ec-a409-f47b099bf663">
<name>
<val>3. Architectural Design</val>
</name>
<ownedDiagram>
<reflist>
<ref refid="37edd9b4-71b5-11ec-a409-f47b099bf663"/>
<ref refid="ad3969b8-71b5-11ec-a409-f47b099bf663"/>
</reflist>
</ownedDiagram>
<ownedType>
<reflist>
<ref refid="b73251a0-71b5-11ec-a409-f47b099bf663"/>
</reflist>
</ownedType>
<package>
<ref refid="58d6c2e8-66f8-11ec-b4c8-0456e5e540ed"/>
</package>
</Package>
<Package id="f3a82730-71b1-11ec-a409-f47b099bf663">
<name>
<val>4. Detailed Design</val>
</name>
<ownedDiagram>
<reflist>
<ref refid="585f224c-71b6-11ec-a409-f47b099bf663"/>
<ref refid="0b5ba60e-71b7-11ec-a409-f47b099bf663"/>
</reflist>
</ownedDiagram>
<package>
<ref refid="58d6c2e8-66f8-11ec-b4c8-0456e5e540ed"/>
</package>
</Package>
<Diagram id="0c81912e-71b2-11ec-a409-f47b099bf663">
<diagramType>
<val>uc</val>
</diagramType>
<element>
<ref refid="a021290e-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Use Cases</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="fe29995e-71b2-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="fe29884c-71b2-11ec-a409-f47b099bf663">
<body>
<val>Analyze functional requirements by
identifying user roles actors and
associating them to their use cases.</val>
</body>
<presentation>
<reflist>
<ref refid="fe29995e-71b2-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="fe29995e-71b2-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 93.76953125, 79.1953125)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>258.0</val>
</width>
<height>
<val>110.0</val>
</height>
<diagram>
<ref refid="0c81912e-71b2-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="fe29884c-71b2-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Diagram id="3132c19a-71b3-11ec-a409-f47b099bf663">
<diagramType>
<val>act</val>
</diagramType>
<element>
<ref refid="a021290e-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Use Case Scenarios</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="7ff4998e-71b3-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="7ff48ef8-71b3-11ec-a409-f47b099bf663">
<body>
<val>Model abstract use case implementation by creating activity diagrams visualizing activity flows for primary and secondary use case scenarios.</val>
</body>
<presentation>
<reflist>
<ref refid="7ff4998e-71b3-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="7ff4998e-71b3-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 58.0, 79.0)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>364.0</val>
</width>
<height>
<val>95.0</val>
</height>
<diagram>
<ref refid="3132c19a-71b3-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="7ff48ef8-71b3-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Diagram id="06ecc092-71b4-11ec-a409-f47b099bf663">
<diagramType>
<val>cls</val>
</diagramType>
<element>
<ref refid="c254a76c-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Domain Entities</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="b2b559de-71b4-11ec-a409-f47b099bf663"/>
<ref refid="20daf629-2260-11ef-b1ab-a1758bde9d62"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="b2b54e26-71b4-11ec-a409-f47b099bf663">
<body>
<val>Perform domain analysis by modeling domain entities and their relationships using simplified class diagram. This diagram will serve as a visual dictionary of concepts. It will also be a starting point for your design-level data model.</val>
</body>
<presentation>
<reflist>
<ref refid="b2b559de-71b4-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="b2b559de-71b4-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 46.015625, 81.69921875)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>400.0</val>
</width>
<height>
<val>100.0</val>
</height>
<diagram>
<ref refid="06ecc092-71b4-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="b2b54e26-71b4-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Diagram id="37edd9b4-71b5-11ec-a409-f47b099bf663">
<diagramType>
<val>pkg</val>
</diagramType>
<element>
<ref refid="cccf183a-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Package Dependencies</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="098cfa2c-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Diagram id="ad3969b8-71b5-11ec-a409-f47b099bf663">
<diagramType>
<val>sd</val>
</diagramType>
<element>
<ref refid="cccf183a-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Interactions</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="2d10bd3a-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="098cef6e-71b6-11ec-a409-f47b099bf663">
<body>
<val>Prepare package dependencies diagram to group your implementation classes in appropriate way. This will help you maintain the code well structured and avoid design flaws such as cyclic dependencies or dependencies on unstable parts</val>
</body>
<presentation>
<reflist>
<ref refid="098cfa2c-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="098cfa2c-71b6-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 106.71484375, 51.49999999999997)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>271.5703125</val>
</width>
<height>
<val>144.0</val>
</height>
<diagram>
<ref refid="37edd9b4-71b5-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="098cef6e-71b6-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Comment id="2d10b29a-71b6-11ec-a409-f47b099bf663">
<body>
<val>Model component interactions for use case scenarios in order to find out new methods in
existing classes or even new classes with specific responsibilities.</val>
</body>
<presentation>
<reflist>
<ref refid="2d10bd3a-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="2d10bd3a-71b6-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 43.0, 73.0)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>322.0</val>
</width>
<height>
<val>93.0</val>
</height>
<diagram>
<ref refid="ad3969b8-71b5-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="2d10b29a-71b6-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Diagram id="585f224c-71b6-11ec-a409-f47b099bf663">
<diagramType>
<val>cls</val>
</diagramType>
<element>
<ref refid="f3a82730-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Detailed Class Design</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="6e4703fe-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="6e46f7ba-71b6-11ec-a409-f47b099bf663">
<body>
<val>Create detailed class diagrams to capture your object-oriented data model.</val>
</body>
<presentation>
<reflist>
<ref refid="6e4703fe-71b6-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="6e4703fe-71b6-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 72.0, 76.5)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>215.0</val>
</width>
<height>
<val>76.0</val>
</height>
<diagram>
<ref refid="585f224c-71b6-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="6e46f7ba-71b6-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Diagram id="0b5ba60e-71b7-11ec-a409-f47b099bf663">
<diagramType>
<val>cmp</val>
</diagramType>
<element>
<ref refid="f3a82730-71b1-11ec-a409-f47b099bf663"/>
</element>
<name>
<val>Implementation Architecture</val>
</name>
<ownedPresentation>
<reflist>
<ref refid="6203ccac-71b7-11ec-a409-f47b099bf663"/>
</reflist>
</ownedPresentation>
</Diagram>
<Comment id="6203b92e-71b7-11ec-a409-f47b099bf663">
<body>
<val>Define the major artifacts that manifest implementation of your components. Indicate how they are deployed on hardware nodes, their inter-dependencies and communication protocols.</val>
</body>
<presentation>
<reflist>
<ref refid="6203ccac-71b7-11ec-a409-f47b099bf663"/>
</reflist>
</presentation>
</Comment>
<CommentItem id="6203ccac-71b7-11ec-a409-f47b099bf663">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, -7.59375, 75.08984375)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>271.0</val>
</width>
<height>
<val>129.0</val>
</height>
<diagram>
<ref refid="0b5ba60e-71b7-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="6203b92e-71b7-11ec-a409-f47b099bf663"/>
</subject>
</CommentItem>
<Interaction id="b73251a0-71b5-11ec-a409-f47b099bf663">
<name>
<val>Interaction</val>
</name>
<package>
<ref refid="cccf183a-71b1-11ec-a409-f47b099bf663"/>
</package>
<presentation>
<reflist>
<ref refid="20daf629-2260-11ef-b1ab-a1758bde9d62"/>
</reflist>
</presentation>
</Interaction>
<InteractionItem id="20daf629-2260-11ef-b1ab-a1758bde9d62">
<matrix>
<val>(1.0, 0.0, 0.0, 1.0, 100.0, 100.0)</val>
</matrix>
<top-left>
<val>(0.0, 0.0)</val>
</top-left>
<width>
<val>150.0</val>
</width>
<height>
<val>100.0</val>
</height>
<diagram>
<ref refid="06ecc092-71b4-11ec-a409-f47b099bf663"/>
</diagram>
<subject>
<ref refid="b73251a0-71b5-11ec-a409-f47b099bf663"/>
</subject>
</InteractionItem>
</gaphor>

View File

@ -1,3 +1,3 @@
CREATE DATABASE IF NOT EXISTS transport_accessibility;
CREATE DATABASE IF NOT EXISTS transport_accessibility DEFAULT CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
CREATE USER IF NOT EXISTS 'transport_accessibility'@'localhost' IDENTIFIED BY 'L8AClYIsC55SEAWTgYopD';
GRANT ALL PRIVILEGES ON transport_accessibility.* TO 'transport_accessibility'@'localhost';

View File

@ -0,0 +1,376 @@
"""
Models
======
Django database models representing the files of the GTFS Reference with all their fields
Attributes
----------
Classes
-------
Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, Pathway, Level, FeedInfo, LocationsGeojson, BookingRule, Translation, Attribution, LocationGroup, LocationGroupStop, RouteNetwork, Network, StopArea, Area, FareMedium, FareProduct, FareLegRule, FareTransferRule, Timeframe
Different files as described in the GTFS Reference
"""
from django.db import models
class Agency(models.Model):
"""
Represents agency.txt from the GTFS Reference.
"""
agency_id = models.CharField(max_length=255, primary_key=True)
agency_name = models.CharField(max_length=255)
agency_url = models.URLField()
agency_timezone = models.CharField(max_length=255)
agency_lang = models.CharField(max_length=2, 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_email = models.EmailField(blank=True, null=True)
class Level(models.Model):
"""
Represents level.txt from the GTFS Reference.
"""
level_id = models.CharField(max_length=255, primary_key=True)
level_index = models.FloatField()
level_name = models.CharField(max_length=255, blank=True, null=True)
class Stop(models.Model):
"""
Represents stop.txt from the GTFS Reference.
"""
stop_id = models.CharField(max_length=255, primary_key=True)
stop_code = models.CharField(max_length=50, blank=True, null=True)
stop_name = models.CharField(max_length=255)
stop_desc = models.TextField(blank=True, null=True)
stop_lat = models.FloatField()
stop_lon = models.FloatField()
zone_id = models.CharField(max_length=255, blank=True, null=True)
stop_url = models.URLField(blank=True, null=True)
location_type = models.IntegerField(blank=True, null=True)
parent_station = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
stop_timezone = models.CharField(max_length=255, 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)
platform_code = models.CharField(max_length=50, blank=True, null=True)
class Route(models.Model):
"""
Represents route.txt from the GTFS Reference.
"""
route_id = models.IntegerField(primary_key=True)
agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
route_short_name = models.CharField(max_length=50)
route_long_name = models.CharField(max_length=255, blank=True, null=True)
route_desc = models.TextField(blank=True, null=True)
route_type = models.IntegerField(default=0)
route_url = models.URLField(blank=True, null=True)
route_color = models.CharField(max_length=6, blank=True, null=True)
route_text_color = models.CharField(max_length=6, blank=True, null=True)
route_sort_order = models.IntegerField(blank=True, null=True)
continuous_pickup = models.IntegerField(blank=True, null=True)
continuous_drop_off = models.IntegerField(blank=True, null=True)
class Shape(models.Model):
"""
Represents shape.txt from the GTFS Reference.
"""
shape_id = models.CharField(max_length=255)
shape_pt_lat = models.FloatField()
shape_pt_lon = models.FloatField()
shape_pt_sequence = models.IntegerField()
shape_dist_traveled = models.FloatField(blank=True, null=True)
class Meta:
unique_together = (('shape_id', 'shape_pt_sequence'),)
class Calendar(models.Model):
"""
Represents calendar.txt from the GTFS Reference.
"""
service_id = models.IntegerField()
monday = models.BooleanField()
tuesday = models.BooleanField()
wednesday = models.BooleanField()
thursday = models.BooleanField()
friday = models.BooleanField()
saturday = models.BooleanField()
sunday = models.BooleanField()
start_date = models.DateField()
end_date = models.DateField()
class CalendarDate(models.Model):
"""
Represents calendar_date.txt from the GTFS Reference.
"""
service_id = models.IntegerField()
date = models.DateField()
exception_type = models.IntegerField()
class Meta:
unique_together = (('service_id', 'date'),)
class Trip(models.Model):
"""
Represents trip.txt from the GTFS Reference.
"""
trip_id = models.CharField(max_length=255, primary_key=True)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
service_id = models.IntegerField()
trip_headsign = models.CharField(max_length=255, blank=True, null=True)
trip_short_name = models.CharField(max_length=255, blank=True, null=True)
direction_id = models.IntegerField(blank=True, null=True)
block_id = models.CharField(max_length=255, blank=True, null=True)
shape_id = models.ForeignKey(Shape, on_delete=models.CASCADE, blank=True)
wheelchair_accessible = models.IntegerField(blank=True, null=True)
bikes_allowed = models.IntegerField(blank=True, null=True)
class LocationGroup(models.Model):
"""
Represents location_group.txt from the GTFS Reference.
"""
location_group_id = models.CharField(max_length=255, primary_key=True)
location_group_name = models.CharField(max_length=255)
location_group_type = models.CharField(max_length=255)
class LocationsGeojson(models.Model):
"""
Represents locations.geojson from the GTFS Reference.
"""
location_id = models.CharField(max_length=255, primary_key=True)
location_name = models.CharField(max_length=255)
location_lat = models.FloatField()
location_lon = models.FloatField()
location_type = models.CharField(max_length=255)
parent_location_id = models.CharField(max_length=255, blank=True, null=True)
wheelchair_boarding = models.BooleanField(blank=True, null=True)
class StopTime(models.Model):
"""
Represents stop_time.txt from the GTFS Reference.
"""
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
arrival_time = models.TimeField(blank=True, null=True)
departure_time = models.TimeField(blank=True, null=True)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
location_group_id = models.ForeignKey(LocationGroup, on_delete=models.SET_NULL, blank=True, null=True)
location_id = models.ForeignKey(LocationsGeojson, on_delete=models.SET_NULL, blank=True, null=True)
stop_sequence = models.IntegerField()
stop_headsign = models.CharField(max_length=255, blank=True, null=True)
pickup_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)
timepoint = models.IntegerField(blank=True, null=True)
class Meta:
unique_together = (('trip_id', 'stop_sequence'),)
class FareAttribute(models.Model):
"""
Represents fare_attribute.txt from the GTFS Reference.
"""
fare_id = models.CharField(max_length=255, primary_key=True)
price = models.FloatField()
currency_type = models.CharField(max_length=3)
payment_method = models.IntegerField()
transfers = models.IntegerField()
agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
transfer_duration = models.IntegerField(blank=True, null=True)
class FareRule(models.Model):
"""
Represents fare_rule.txt from the GTFS Reference.
"""
fare_id = models.ForeignKey(FareAttribute, on_delete=models.CASCADE)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE, blank=True, null=True)
origin_id = models.IntegerField(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)
class Frequency(models.Model):
"""
Represents frequency.txt from the GTFS Reference.
"""
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
start_time = models.TimeField()
end_time = models.TimeField()
headway_secs = models.IntegerField()
exact_times = models.IntegerField(blank=True, null=True)
class Transfer(models.Model):
"""
Represents transfer.txt from the GTFS Reference.
"""
from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_from_stop')
to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_to_stop')
from_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_route')
to_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_route')
from_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_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()
min_transfer_time = models.IntegerField(blank=True, null=True)
class Meta:
unique_together = (('from_stop', 'to_stop'),)
class Pathway(models.Model):
"""
Represents lathway.txt from the GTFS Reference.
"""
pathway_id = models.CharField(max_length=255, primary_key=True)
from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_from')
to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_to')
pathway_mode = models.IntegerField()
is_bidirectional = models.IntegerField()
length = models.FloatField(blank=True, null=True)
traversal_time = models.IntegerField(blank=True, null=True)
stair_count = models.IntegerField(blank=True, null=True)
max_slope = 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)
reversed_signposted_as = models.CharField(max_length=255, blank=True, null=True)
class FeedInfo(models.Model):
"""
Represents feed_info.txt from the GTFS Reference.
"""
feed_publisher_name = models.CharField(max_length=255)
feed_publisher_url = models.URLField()
feed_lang = models.CharField(max_length=255)
default_lang = models.CharField(max_length=255, blank=True, null=True)
feed_start_date = models.DateField(blank=True, null=True)
feed_end_date = models.DateField(blank=True, null=True)
feed_version = models.CharField(max_length=255, blank=True, null=True)
feed_contact_email = models.EmailField(blank=True, null=True)
feed_contact_url = models.URLField(blank=True, null=True)
feed_id = models.BigAutoField(primary_key=True)
class BookingRule(models.Model):
"""
Represents booking_rule.txt from the GTFS Reference.
"""
booking_rule_id = models.CharField(max_length=255, primary_key=True)
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
start_time = models.TimeField(blank=True, null=True)
end_time = models.TimeField(blank=True, null=True)
booking_type = models.CharField(max_length=255)
rule_criteria = models.TextField(blank=True, null=True)
booking_rule_instructions = models.TextField(blank=True, null=True)
class Translation(models.Model):
"""
Represents translation.txt from the GTFS Reference.
"""
table_name = models.CharField(max_length=255)
field_name = models.CharField(max_length=255)
language = models.CharField(max_length=2)
translation = models.TextField()
class Attribution(models.Model):
"""
Represents attribution.txt from the GTFS Reference.
"""
attribution_id = models.BigAutoField(primary_key=True)
agency_id = models.ForeignKey(Agency, on_delete=models.SET_NULL, blank=True, null=True)
route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True)
trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True)
attribution_name = models.CharField(max_length=255)
attribution_url = models.URLField()
attribution_email = models.EmailField(blank=True, null=True)
attribution_phone = models.CharField(max_length=50, blank=True, null=True)
class LocationGroupStop(models.Model):
"""
Represents location_groupStop.txt from the GTFS Reference.
"""
location_group_id = models.ForeignKey(LocationGroup, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
class Network(models.Model):
"""
Represents network.txt from the GTFS Reference.
"""
network_id = models.CharField(max_length=255, primary_key=True)
network_name = models.CharField(max_length=255)
class RouteNetwork(models.Model):
"""
Represents route_network.txt from the GTFS Reference.
"""
route_network_id = models.CharField(max_length=255, primary_key=True)
route_network_name = models.CharField(max_length=255)
network_id = models.ForeignKey(Network, on_delete=models.CASCADE)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
class Area(models.Model):
"""
Represents area.txt from the GTFS Reference.
"""
area_id = models.CharField(max_length=255, primary_key=True)
area_name = models.CharField(max_length=255)
area_description = models.TextField(blank=True, null=True)
class StopArea(models.Model):
"""
Represents stop_area.txt from the GTFS Reference.
"""
stop_area_id = models.CharField(max_length=255, primary_key=True)
stop_area_name = models.CharField(max_length=255)
stop_area_description = models.TextField(blank=True, null=True)
area_id = models.ForeignKey(Area, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
class FareMedium(models.Model):
"""
Represents fare_medium.txt from the GTFS Reference.
"""
fare_media_id = models.CharField(max_length=255, primary_key=True)
fare_media_name = models.CharField(max_length=255)
fare_media_description = models.TextField(blank=True, null=True)
class FareProduct(models.Model):
"""
Represents fare_product.txt from the GTFS Reference.
"""
fare_product_id = models.BigAutoField(primary_key=True)
fare_product_name = models.CharField(max_length=255)
fare_product_description = models.TextField(blank=True, null=True)
amount = models.FloatField()
curreny = models.CharField(max_length=64)
class Timeframe(models.Model):
"""
Represents timeframe.txt from the GTFS Reference.
"""
timeframe_group_id = models.IntegerField(primary_key=True)
service_id = models.IntegerField()
start_date = models.DateField()
end_date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
class FareLegRule(models.Model):
"""
Represents fare_legRule.txt from the GTFS Reference.
"""
fare_leg_rule_id = models.CharField(max_length=255, primary_key=True)
fare_leg_rule_name = models.CharField(max_length=255)
fare_leg_rule_description = models.TextField(blank=True, null=True)
network_id = models.ForeignKey(Network, blank=True, null=True, on_delete=models.SET_NULL)
from_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_area')
to_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_area')
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')
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.CASCADE)
class FareTransferRule(models.Model):
"""
Represents faretransfer_rule.txt from the GTFS Reference.
"""
fare_transfer_rule_id = models.CharField(max_length=255, primary_key=True)
fare_transfer_rule_name = models.CharField(max_length=255)
fare_transfer_rule_description = models.TextField(blank=True, null=True)
from_leg_group_id = models.IntegerField(blank=True, null=True)
to_leg_group_id = models.IntegerField(blank=True, null=True)
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.SET_NULL, blank=True, null=True)

View File

@ -0,0 +1,28 @@
BEGIN{
classname = ""
FS = "[ |(,]"
printf "[\n"
}
{
#print "1: "$1 " 2: "$2 " 3: "$3 " 4: "$4
if ($1 == "class") {
classname = $2
printf "\t(pt_map.models." classname ", ["
}else if ($0 == "" && classname != ""){
printf "]),\n"
classname = ""
}else {
fk = index($0, "models.ForeignKey")
if (fk > 0) {
first = match($0, /\(/)+1
last = index(substr($0, first), ",")-1
printf "(pt_map.models." substr($0, first, last) ", "
first = match($0, /[a-z]/)
last = index(substr($0, first), " = ")-1
printf "\'" substr($0, first, last) "\'), "
}
}
}
END{
print "]"
}

View File

@ -443,7 +443,6 @@ def to_snake_case(name):
def unqfk(ts, fk):
if not isinstance(fk, str):
fk = str(int(fk))
print(f"fk: {fk}")
return f"{ts}{fk}".strip()
def gtfs_to_db(g: pt_map.gtfs.GTFS):
@ -468,6 +467,9 @@ def gtfs_to_db(g: pt_map.gtfs.GTFS):
if row.get(fk[1]):
row[fk[1]] = fk[0].objects.get(**{primary_keys[fk[0]]: unqfk(ts, row[fk[1]])})
defaults = {field: stdz(row.get(field), m, field) for field in v if row.get(field) and not is_NaN(row[field])}
print(model[0])
if model[0] == pt_map.models.StopTime:
print(row)
if primary_keys[m]:
row[primary_keys[m]] = unqfk(ts, row[primary_keys[m]])
defaults[primary_keys[m]] = row[primary_keys[m]]
@ -481,7 +483,7 @@ def gtfs_to_db(g: pt_map.gtfs.GTFS):
**{primary_keys[m]: row[primary_keys[m]]}
)
else:
m.objects.update_or_create(defaults=defaults)
m.objects.create(**defaults)
reversed_file_mapping = {

View File

@ -0,0 +1,240 @@
gtfs_schema = {
"agency": [
"agency_id",
"agency_name",
"agency_url",
"agency_timezone",
"agency_lang",
"agency_phone",
"agency_email",
"agency_fare_url"
],
"stops": [
"stop_id",
"stop_code",
"stop_name",
"stop_desc",
"stop_lat",
"stop_lon",
"zone_id",
"stop_url",
"location_type",
"parent_station",
"stop_timezone",
"wheelchair_boarding",
"level_id",
"platform_code"
],
"routes": [
"route_id",
"agency_id",
"route_short_name",
"route_long_name",
"route_desc",
"route_type",
"route_url",
"route_color",
"route_text_color",
"route_sort_order",
"continuous_pickup",
"continuous_drop_off"
],
"trips": [
"trip_id",
"route_id",
"service_id",
"trip_headsign",
"trip_short_name",
"direction_id",
"block_id",
"shape_id",
"wheelchair_accessible",
"bikes_allowed"
],
"stop_times": [
"trip_id",
"arrival_time",
"departure_time",
"stop_id",
"stop_sequence",
"stop_headsign",
"pickup_type",
"drop_off_type",
"shape_dist_traveled",
"timepoint"
],
"calendar": [
"service_id",
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday",
"start_date",
"end_date"
],
"calendar_dates": [
"service_id",
"date",
"exception_type"
],
"fare_attributes": [
"fare_id",
"price",
"currency_type",
"payment_method",
"transfers",
"transfer_duration"
],
"fare_rules": [
"fare_id",
"route_id",
"origin_id",
"destination_id",
"contains_id"
],
"timeframes": [
"timeframe_id",
"start_time",
"end_time",
"headway_sec",
"exact_times"
],
"fare_media": [
"media_id",
"agency_id",
"fare_id",
"seat_type",
"price"
],
"fare_products": [
"product_id",
"agency_id",
"product_type",
"fare_id",
"product_name",
"short_name",
"description",
"duration",
"transfers"
],
"fare_leg_rules": [
"fare_id",
"route_id",
"origin_id",
"destination_id",
"contains_id"
],
"fare_transfer_rules": [
"from_fare_id",
"to_fare_id",
"transfer_type",
"min_transfer_time"
],
"areas": [
"area_id",
"area_name",
"area_description"
],
"stop_areas": [
"stop_area_id",
"stop_id",
"area_id",
"location_type",
"parent_station",
"fare_zone_id"
],
"networks": [
"network_id",
"network_name",
"network_description"
],
"route_networks": [
"route_id",
"network_id"
],
"shapes": [
"shape_id",
"shape_pt_lat",
"shape_pt_lon",
"shape_pt_sequence",
"shape_dist_traveled"
],
"frequencies": [
"trip_id",
"start_time",
"end_time",
"headway_secs",
"exact_times"
],
"transfers": [
"from_stop_id",
"to_stop_id",
"transfer_type",
"min_transfer_time"
],
"pathways": [
"pathway_id",
"from_stop_id",
"to_stop_id",
"pathway_mode",
"is_bidirectional",
"length",
"traversal_time",
"stair_count",
"max_slope",
"min_width",
"signposted_as",
"reversed_signposted_as"
],
"levels": [
"level_id",
"level_index",
"level_name"
],
"location_groups": [
"location_group_id",
"location_group_name"
],
"location_group_stops": [
"location_group_id",
"stop_id"
],
"locations_geojson": [
"type",
"features"
],
"booking_rules": [
"rule_id",
"stop_id",
"rule_type",
"booking_url",
"admission_rules",
"admission_requirements"
],
"translations": [
"table_name",
"field_name",
"language",
"translation"
],
"feed_info": [
"feed_publisher_name",
"feed_publisher_url",
"feed_lang",
"default_lang",
"feed_start_date",
"feed_end_date",
"feed_version",
"feed_contact_email",
"feed_contact_url"
],
"attributions": [
"attribution_id",
"organization_name",
"is_producer"
]
}

View File

@ -1,29 +0,0 @@
# Generated by Django 5.0.6 on 2024-05-31 22:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0001_initial'),
]
operations = [
migrations.AlterUniqueTogether(
name='calendardate',
unique_together={('service_id', 'date')},
),
migrations.AlterUniqueTogether(
name='shape',
unique_together={('shape_id', 'shape_pt_sequence')},
),
migrations.AlterUniqueTogether(
name='stoptime',
unique_together={('trip', 'stop_sequence')},
),
migrations.AlterUniqueTogether(
name='transfer',
unique_together={('from_stop', 'to_stop')},
),
]

View File

@ -1,38 +0,0 @@
# Generated by Django 5.0.6 on 2024-05-31 23:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0002_alter_calendardate_unique_together_and_more'),
]
operations = [
migrations.AlterField(
model_name='calendar',
name='service_id',
field=models.IntegerField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='fareattribute',
name='fare_id',
field=models.IntegerField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='feedinfo',
name='feed_id',
field=models.IntegerField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='route',
name='route_id',
field=models.IntegerField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='trip',
name='trip_id',
field=models.IntegerField(primary_key=True, serialize=False),
),
]

View File

@ -1,48 +0,0 @@
# Generated by Django 5.0.6 on 2024-05-31 23:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0003_alter_calendar_service_id_and_more'),
]
operations = [
migrations.AlterField(
model_name='agency',
name='agency_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='calendar',
name='service_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='fareattribute',
name='fare_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='feedinfo',
name='feed_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='route',
name='route_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='stop',
name='stop_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='trip',
name='trip_id',
field=models.BigAutoField(primary_key=True, serialize=False),
),
]

View File

@ -1,205 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 11:40
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0004_alter_agency_agency_id_alter_calendar_service_id_and_more'),
]
operations = [
migrations.CreateModel(
name='Level',
fields=[
('level_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('level_index', models.FloatField()),
('level_name', models.CharField(blank=True, max_length=255, null=True)),
],
),
migrations.RemoveField(
model_name='stop',
name='tts_stop_name',
),
migrations.AddField(
model_name='agency',
name='agency_lang',
field=models.CharField(blank=True, max_length=2, null=True),
),
migrations.AddField(
model_name='agency',
name='agency_timezone',
field=models.CharField(default=django.utils.timezone.now, max_length=255),
preserve_default=False,
),
migrations.AddField(
model_name='feedinfo',
name='default_lang',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='feedinfo',
name='feed_contact_email',
field=models.EmailField(blank=True, max_length=254, null=True),
),
migrations.AddField(
model_name='feedinfo',
name='feed_contact_url',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='route',
name='continuous_drop_off',
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='route',
name='continuous_pickup',
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='route',
name='route_sort_order',
field=models.IntegerField(blank=True, null=True),
),
migrations.AlterField(
model_name='agency',
name='agency_email',
field=models.EmailField(blank=True, max_length=254, null=True),
),
migrations.AlterField(
model_name='agency',
name='agency_fare_url',
field=models.URLField(blank=True, null=True),
),
migrations.AlterField(
model_name='agency',
name='agency_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='agency',
name='agency_name',
field=models.CharField(max_length=255),
),
migrations.AlterField(
model_name='agency',
name='agency_phone',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='calendar',
name='service_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='calendardate',
name='service_id',
field=models.CharField(max_length=255),
),
migrations.AlterField(
model_name='fareattribute',
name='currency_type',
field=models.CharField(max_length=3),
),
migrations.AlterField(
model_name='fareattribute',
name='fare_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='route',
name='agency',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pt_map.agency'),
),
migrations.AlterField(
model_name='route',
name='route_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='route',
name='route_long_name',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='route',
name='route_short_name',
field=models.CharField(max_length=50),
),
migrations.AlterField(
model_name='stop',
name='platform_code',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='stop',
name='stop_code',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='stop',
name='stop_desc',
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name='stop',
name='stop_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='stop',
name='stop_lat',
field=models.FloatField(),
),
migrations.AlterField(
model_name='stop',
name='stop_lon',
field=models.FloatField(),
),
migrations.AlterField(
model_name='stop',
name='stop_name',
field=models.CharField(max_length=255),
),
migrations.AlterField(
model_name='stop',
name='zone_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='stoptime',
name='arrival_time',
field=models.TimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='stoptime',
name='departure_time',
field=models.TimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='trip',
name='trip_id',
field=models.CharField(max_length=255, primary_key=True, serialize=False),
),
migrations.CreateModel(
name='Pathway',
fields=[
('pathway_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('pathway_mode', models.IntegerField()),
('is_bidirectional', models.IntegerField()),
('length', models.FloatField(blank=True, null=True)),
('traversal_time', models.IntegerField(blank=True, null=True)),
('stair_count', models.IntegerField(blank=True, null=True)),
('max_slope', models.FloatField(blank=True, null=True)),
('min_width', models.FloatField(blank=True, null=True)),
('signposted_as', models.CharField(blank=True, max_length=255, null=True)),
('reversed_signposted_as', models.CharField(blank=True, max_length=255, null=True)),
('from_stop', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pathways_from', to='pt_map.stop')),
('to_stop', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pathways_to', to='pt_map.stop')),
],
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 12:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0005_level_remove_stop_tts_stop_name_agency_agency_lang_and_more'),
]
operations = [
migrations.AlterField(
model_name='route',
name='route_type',
field=models.IntegerField(default=0),
),
]

View File

@ -1,59 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 16:56
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0006_alter_route_route_type'),
]
operations = [
migrations.CreateModel(
name='Location',
fields=[
('location_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('location_name', models.CharField(max_length=255)),
('location_lat', models.FloatField()),
('location_lon', models.FloatField()),
('location_type', models.CharField(max_length=255)),
('parent_location_id', models.CharField(blank=True, max_length=255, null=True)),
('wheelchair_boarding', models.BooleanField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='Translation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('table_name', models.CharField(max_length=255)),
('field_name', models.CharField(max_length=255)),
('language', models.CharField(max_length=2)),
('translation', models.TextField()),
],
),
migrations.CreateModel(
name='Attribution',
fields=[
('attribution_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('attribution_name', models.CharField(max_length=255)),
('attribution_url', models.URLField()),
('attribution_email', models.EmailField(blank=True, max_length=254, null=True)),
('attribution_phone', models.CharField(blank=True, max_length=50, null=True)),
('agency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pt_map.agency')),
],
),
migrations.CreateModel(
name='BookingRule',
fields=[
('booking_rule_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('start_time', models.TimeField(blank=True, null=True)),
('end_time', models.TimeField(blank=True, null=True)),
('booking_type', models.CharField(max_length=255)),
('rule_criteria', models.TextField(blank=True, null=True)),
('booking_rule_instructions', models.TextField(blank=True, null=True)),
('trip', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pt_map.trip')),
],
),
]

View File

@ -1,102 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 17:04
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0007_location_translation_attribution_bookingrule'),
]
operations = [
migrations.CreateModel(
name='Area',
fields=[
('area_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('area_name', models.CharField(max_length=255)),
('area_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='FareLegRule',
fields=[
('fare_leg_rule_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('fare_leg_rule_name', models.CharField(max_length=255)),
('fare_leg_rule_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='FareMedia',
fields=[
('fare_media_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('fare_media_name', models.CharField(max_length=255)),
('fare_media_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='FareProduct',
fields=[
('fare_product_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('fare_product_name', models.CharField(max_length=255)),
('fare_product_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='FareTransferRule',
fields=[
('fare_transfer_rule_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('fare_transfer_rule_name', models.CharField(max_length=255)),
('fare_transfer_rule_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='LocationGroup',
fields=[
('location_group_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('location_group_name', models.CharField(max_length=255)),
('location_group_type', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='Network',
fields=[
('network_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('network_name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='RouteNetwork',
fields=[
('route_network_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('route_network_name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='StopArea',
fields=[
('stop_area_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('stop_area_name', models.CharField(max_length=255)),
('stop_area_description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='TimeFrame',
fields=[
('time_frame_id', models.CharField(max_length=255, primary_key=True, serialize=False)),
('start_date', models.DateField()),
('end_date', models.DateField()),
('start_time', models.TimeField()),
('end_time', models.TimeField()),
],
),
migrations.CreateModel(
name='LocationGroupStop',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('location_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pt_map.locationgroup')),
('stop', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pt_map.stop')),
],
),
]

View File

@ -1,17 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 17:10
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0008_area_farelegrule_faremedia_fareproduct_and_more'),
]
operations = [
migrations.RenameModel(
old_name='FareMedia',
new_name='FareMedium',
),
]

View File

@ -1,17 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 17:19
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0009_rename_faremedia_faremedium'),
]
operations = [
migrations.RenameModel(
old_name='Location',
new_name='LocationGeojson',
),
]

View File

@ -1,17 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-02 17:21
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pt_map', '0010_rename_location_locationgeojson'),
]
operations = [
migrations.RenameModel(
old_name='LocationGeojson',
new_name='LocationsGeojson',
),
]

View File

@ -11,6 +11,7 @@ Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, Fare
Different files as described in the GTFS Reference
"""
from django.db import models
from pt_map.gtfs_schema import gtfs_schema
class Agency(models.Model):
"""
@ -25,6 +26,14 @@ class Agency(models.Model):
agency_fare_url = models.URLField(blank=True, null=True)
agency_email = models.EmailField(blank=True, null=True)
class Level(models.Model):
"""
Represents level.txt from the GTFS Reference.
"""
level_id = models.CharField(max_length=255, primary_key=True)
level_index = models.FloatField()
level_name = models.CharField(max_length=255, blank=True, null=True)
class Stop(models.Model):
"""
Represents stop.txt from the GTFS Reference.
@ -38,18 +47,18 @@ class Stop(models.Model):
zone_id = models.CharField(max_length=255, blank=True, null=True)
stop_url = models.URLField(blank=True, null=True)
location_type = models.IntegerField(blank=True, null=True)
parent_station = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True)
parent_station = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
stop_timezone = models.CharField(max_length=255, blank=True, null=True)
wheelchair_boarding = models.IntegerField(blank=True, null=True)
level_id = models.CharField(max_length=255, 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)
class Route(models.Model):
"""
Represents route.txt from the GTFS Reference.
"""
route_id = models.CharField(max_length=255, primary_key=True)
agency = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
route_id = models.CharField(max_length=255,primary_key=True)
agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
route_short_name = models.CharField(max_length=50)
route_long_name = models.CharField(max_length=255, blank=True, null=True)
route_desc = models.TextField(blank=True, null=True)
@ -61,44 +70,24 @@ class Route(models.Model):
continuous_pickup = models.IntegerField(blank=True, null=True)
continuous_drop_off = models.IntegerField(blank=True, null=True)
class Trip(models.Model):
class Shape(models.Model):
"""
Represents trip.txt from the GTFS Reference.
Represents shape.txt from the GTFS Reference.
"""
trip_id = models.CharField(max_length=255, primary_key=True)
route = models.ForeignKey(Route, on_delete=models.CASCADE)
service_id = models.CharField(max_length=255)
trip_headsign = models.CharField(max_length=255, blank=True, null=True)
trip_short_name = models.CharField(max_length=255, blank=True, null=True)
direction_id = models.IntegerField(blank=True, null=True)
block_id = models.CharField(max_length=255, blank=True, null=True)
shape_id = models.CharField(max_length=255, blank=True, null=True)
wheelchair_accessible = models.IntegerField(blank=True, null=True)
bikes_allowed = models.IntegerField(blank=True, null=True)
class StopTime(models.Model):
"""
Represents stop_time.txt from the GTFS Reference.
"""
trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
arrival_time = models.TimeField(blank=True, null=True)
departure_time = models.TimeField(blank=True, null=True)
stop = models.ForeignKey(Stop, on_delete=models.CASCADE)
stop_sequence = models.IntegerField()
stop_headsign = models.CharField(max_length=255, blank=True, null=True)
pickup_type = models.IntegerField(blank=True, null=True)
drop_off_type = models.IntegerField(blank=True, null=True)
shape_id = models.CharField(max_length=255)
shape_pt_lat = models.FloatField()
shape_pt_lon = models.FloatField()
shape_pt_sequence = models.IntegerField()
shape_dist_traveled = models.FloatField(blank=True, null=True)
timepoint = models.IntegerField(blank=True, null=True)
class Meta:
unique_together = (('trip', 'stop_sequence'),)
unique_together = (('shape_id', 'shape_pt_sequence'),)
class Calendar(models.Model):
"""
Represents calendar.txt from the GTFS Reference.
"""
service_id = models.CharField(max_length=255, primary_key=True)
service_id = models.CharField(max_length=255,primary_key=True)
monday = models.BooleanField()
tuesday = models.BooleanField()
wednesday = models.BooleanField()
@ -120,6 +109,75 @@ class CalendarDate(models.Model):
class Meta:
unique_together = (('service_id', 'date'),)
class Trip(models.Model):
"""
Represents trip.txt from the GTFS Reference.
"""
trip_id = models.CharField(max_length=255, primary_key=True)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
service_id = models.IntegerField()
trip_headsign = models.CharField(max_length=255, blank=True, null=True)
trip_short_name = models.CharField(max_length=255, blank=True, null=True)
direction_id = models.IntegerField(blank=True, null=True)
block_id = models.CharField(max_length=255, blank=True, null=True)
shape_id = models.ForeignKey(Shape, on_delete=models.CASCADE, blank=True)
wheelchair_accessible = models.IntegerField(blank=True, null=True)
bikes_allowed = models.IntegerField(blank=True, null=True)
def as_dict(self):
return {
"trip_id": self.trip_id,
"route_id": self.route_id.route_id,
"service_id": self.service_id,
"trip_headsign": self.trip_headsign,
"trip_short_name": self.trip_short_name,
"direction_id": self.direction_id,
"block_id": self.block_id,
"shape_id": self.shape_id.shape_id,
"wheelchair_accessible": self.wheelchair_accessible,
"bikes_allowed": self.bikes_allowed,
}
class LocationGroup(models.Model):
"""
Represents location_group.txt from the GTFS Reference.
"""
location_group_id = models.CharField(max_length=255, primary_key=True)
location_group_name = models.CharField(max_length=255)
location_group_type = models.CharField(max_length=255)
class LocationsGeojson(models.Model):
"""
Represents locations.geojson from the GTFS Reference.
"""
location_id = models.CharField(max_length=255, primary_key=True)
location_name = models.CharField(max_length=255)
location_lat = models.FloatField()
location_lon = models.FloatField()
location_type = models.CharField(max_length=255)
parent_location_id = models.CharField(max_length=255, blank=True, null=True)
wheelchair_boarding = models.BooleanField(blank=True, null=True)
class StopTime(models.Model):
"""
Represents stop_time.txt from the GTFS Reference.
"""
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
arrival_time = models.TimeField(blank=True, null=True)
departure_time = models.TimeField(blank=True, null=True)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
location_group_id = models.ForeignKey(LocationGroup, on_delete=models.SET_NULL, blank=True, null=True)
location_id = models.ForeignKey(LocationsGeojson, on_delete=models.SET_NULL, blank=True, null=True)
stop_sequence = models.IntegerField()
stop_headsign = models.CharField(max_length=255, blank=True, null=True)
pickup_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)
timepoint = models.IntegerField(blank=True, null=True)
class Meta:
unique_together = (('trip_id', 'stop_sequence'),)
class FareAttribute(models.Model):
"""
Represents fare_attribute.txt from the GTFS Reference.
@ -129,37 +187,24 @@ class FareAttribute(models.Model):
currency_type = models.CharField(max_length=3)
payment_method = models.IntegerField()
transfers = models.IntegerField()
agency = 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)
class FareRule(models.Model):
"""
Represents fare_rule.txt from the GTFS Reference.
"""
fare = models.ForeignKey(FareAttribute, on_delete=models.CASCADE)
route = models.ForeignKey(Route, on_delete=models.CASCADE, blank=True, null=True)
origin_id = models.CharField(max_length=255, blank=True, null=True)
fare_id = models.ForeignKey(FareAttribute, on_delete=models.CASCADE)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE, blank=True, null=True)
origin_id = models.IntegerField(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)
class Shape(models.Model):
"""
Represents shape.txt from the GTFS Reference.
"""
shape_id = models.CharField(max_length=255)
shape_pt_lat = models.FloatField()
shape_pt_lon = models.FloatField()
shape_pt_sequence = models.IntegerField()
shape_dist_traveled = models.FloatField(blank=True, null=True)
class Meta:
unique_together = (('shape_id', 'shape_pt_sequence'),)
class Frequency(models.Model):
"""
Represents frequency.txt from the GTFS Reference.
"""
trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
start_time = models.TimeField()
end_time = models.TimeField()
headway_secs = models.IntegerField()
@ -169,21 +214,25 @@ class Transfer(models.Model):
"""
Represents transfer.txt from the GTFS Reference.
"""
from_stop = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_from')
to_stop = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_to')
from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_from_stop')
to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_to_stop')
from_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_route')
to_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_route')
from_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_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()
min_transfer_time = models.IntegerField(blank=True, null=True)
class Meta:
unique_together = (('from_stop', 'to_stop'),)
unique_together = (('from_stop_id', 'to_stop_id'),)
class Pathway(models.Model):
"""
Represents lathway.txt from the GTFS Reference.
"""
pathway_id = models.CharField(max_length=255, primary_key=True)
from_stop = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_from')
to_stop = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_to')
from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_from')
to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_to')
pathway_mode = models.IntegerField()
is_bidirectional = models.IntegerField()
length = models.FloatField(blank=True, null=True)
@ -194,14 +243,6 @@ class Pathway(models.Model):
signposted_as = models.CharField(max_length=255, blank=True, null=True)
reversed_signposted_as = models.CharField(max_length=255, blank=True, null=True)
class Level(models.Model):
"""
Represents level.txt from the GTFS Reference.
"""
level_id = models.CharField(max_length=255, primary_key=True)
level_index = models.FloatField()
level_name = models.CharField(max_length=255, blank=True, null=True)
class FeedInfo(models.Model):
"""
Represents feed_info.txt from the GTFS Reference.
@ -217,24 +258,12 @@ class FeedInfo(models.Model):
feed_contact_url = models.URLField(blank=True, null=True)
feed_id = models.BigAutoField(primary_key=True)
class LocationsGeojson(models.Model):
"""
Represents locations.geojson from the GTFS Reference.
"""
location_id = models.CharField(max_length=255, primary_key=True)
location_name = models.CharField(max_length=255)
location_lat = models.FloatField()
location_lon = models.FloatField()
location_type = models.CharField(max_length=255)
parent_location_id = models.CharField(max_length=255, blank=True, null=True)
wheelchair_boarding = models.BooleanField(blank=True, null=True)
class BookingRule(models.Model):
"""
Represents booking_rule.txt from the GTFS Reference.
"""
booking_rule_id = models.CharField(max_length=255, primary_key=True)
trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
start_time = models.TimeField(blank=True, null=True)
end_time = models.TimeField(blank=True, null=True)
booking_type = models.CharField(max_length=255)
@ -254,34 +283,21 @@ class Attribution(models.Model):
"""
Represents attribution.txt from the GTFS Reference.
"""
attribution_id = models.CharField(max_length=255, primary_key=True)
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
attribution_id = models.BigAutoField(primary_key=True)
agency_id = models.ForeignKey(Agency, on_delete=models.SET_NULL, blank=True, null=True)
route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True)
trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True)
attribution_name = models.CharField(max_length=255)
attribution_url = models.URLField()
attribution_email = models.EmailField(blank=True, null=True)
attribution_phone = models.CharField(max_length=50, blank=True, null=True)
class LocationGroup(models.Model):
"""
Represents location_group.txt from the GTFS Reference.
"""
location_group_id = models.CharField(max_length=255, primary_key=True)
location_group_name = models.CharField(max_length=255)
location_group_type = models.CharField(max_length=255)
class LocationGroupStop(models.Model):
"""
Represents location_groupStop.txt from the GTFS Reference.
"""
location_group = models.ForeignKey(LocationGroup, on_delete=models.CASCADE)
stop = models.ForeignKey(Stop, on_delete=models.CASCADE)
class RouteNetwork(models.Model):
"""
Represents route_network.txt from the GTFS Reference.
"""
route_network_id = models.CharField(max_length=255, primary_key=True)
route_network_name = models.CharField(max_length=255)
location_group_id = models.ForeignKey(LocationGroup, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
class Network(models.Model):
"""
@ -290,13 +306,14 @@ class Network(models.Model):
network_id = models.CharField(max_length=255, primary_key=True)
network_name = models.CharField(max_length=255)
class StopArea(models.Model):
class RouteNetwork(models.Model):
"""
Represents stop_area.txt from the GTFS Reference.
Represents route_network.txt from the GTFS Reference.
"""
stop_area_id = models.CharField(max_length=255, primary_key=True)
stop_area_name = models.CharField(max_length=255)
stop_area_description = models.TextField(blank=True, null=True)
route_network_id = models.CharField(max_length=255, primary_key=True)
route_network_name = models.CharField(max_length=255)
network_id = models.ForeignKey(Network, on_delete=models.CASCADE)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
class Area(models.Model):
"""
@ -306,6 +323,16 @@ class Area(models.Model):
area_name = models.CharField(max_length=255)
area_description = models.TextField(blank=True, null=True)
class StopArea(models.Model):
"""
Represents stop_area.txt from the GTFS Reference.
"""
stop_area_id = models.CharField(max_length=255, primary_key=True)
stop_area_name = models.CharField(max_length=255)
stop_area_description = models.TextField(blank=True, null=True)
area_id = models.ForeignKey(Area, on_delete=models.CASCADE)
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
class FareMedium(models.Model):
"""
Represents fare_medium.txt from the GTFS Reference.
@ -318,9 +345,22 @@ class FareProduct(models.Model):
"""
Represents fare_product.txt from the GTFS Reference.
"""
fare_product_id = models.CharField(max_length=255, primary_key=True)
fare_product_id = models.BigAutoField(primary_key=True)
fare_product_name = models.CharField(max_length=255)
fare_product_description = models.TextField(blank=True, null=True)
amount = models.FloatField()
curreny = models.CharField(max_length=64)
class Timeframe(models.Model):
"""
Represents timeframe.txt from the GTFS Reference.
"""
timeframe_group_id = models.CharField(max_length=255,primary_key=True)
service_id = models.IntegerField()
start_date = models.DateField()
end_date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
class FareLegRule(models.Model):
"""
@ -329,6 +369,12 @@ class FareLegRule(models.Model):
fare_leg_rule_id = models.CharField(max_length=255, primary_key=True)
fare_leg_rule_name = models.CharField(max_length=255)
fare_leg_rule_description = models.TextField(blank=True, null=True)
network_id = models.ForeignKey(Network, blank=True, null=True, on_delete=models.SET_NULL)
from_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_area')
to_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_area')
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')
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.CASCADE)
class FareTransferRule(models.Model):
"""
@ -337,14 +383,9 @@ class FareTransferRule(models.Model):
fare_transfer_rule_id = models.CharField(max_length=255, primary_key=True)
fare_transfer_rule_name = models.CharField(max_length=255)
fare_transfer_rule_description = models.TextField(blank=True, null=True)
from_leg_group_id = models.IntegerField(blank=True, null=True)
to_leg_group_id = models.IntegerField(blank=True, null=True)
fare_product_id = models.ForeignKey(FareProduct, on_delete=models.SET_NULL, blank=True, null=True)
class Timeframe(models.Model):
"""
Represents timeframe.txt from the GTFS Reference.
"""
time_frame_id = models.CharField(max_length=255, primary_key=True)
start_date = models.DateField()
end_date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()

View File

@ -0,0 +1,57 @@
"""
Query
=====
Interface between backend/database and Views. Aims to abstract database lookups for the frontend as well as possible.
Contents
--------
Classes
-------
Functions
---------
Public variables
----------------
"""
import django.db.models
import pt_map.models
from pt_map.class_names import class_names
class GTFSQuery:
"""
Base datatype conveniently storing data requiring queries involving multiple tables as if they were a GTFS Feed as described by the GTFS specification.
Main abstraction element between data handling and frontend.
Attributes
----------
Methods
-------
"""
def __init__(self, queries: dict[str, django.db.models.query.QuerySet]):
"""
Parameters
----------
queries : dict[str, django.db.models.query.QuerySet]
dict containing
keys: str specifying the file of the GTFS reference they represent either as the file name omitting the extension or as Model name in CamelCase or as model name all lower case.
values: QuerySets of the specified models
Raises
------
TypeError
If queries is not present or of bad type
ValueError
If queries contains a Key not specified as a file in the GTFS reference
"""
if not queries or not isinstance(queries, dict):
raise TypeError("Missing dict of QuerySets")
for key,value in queries.items():
for names in class_names:
if names.get(key):
cls = names[key]
if not cls:
raise ValueError("Bad GTFS file name")

View File

@ -10,9 +10,26 @@ index(request)
"""
from django.shortcuts import render
from django.http import HttpResponse
from .models import Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, FeedInfo
from .models import *
def print_r(r, s):
if not len(r):
print(s)
return r
def index(request):
context = {}
return HttpResponse(request, "templates/map.html", context)
stops = [{name: getattr(s, name) for name in ['stop_id', '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
routes = [{"route_id": r.route_id, "route_type": r.route_type, "route_name": route_name(r), "agency_id": r.agency_id.agency_id} for r in Route.objects.all()]
trips = {r["route_id"]: [t for t in Trip.objects.filter(route_id_id=r["route_id"])] for r in routes}
#stop_sequence = {}
#for r in routes:
# seq = []
# for s in StopTime.objects.filter(trip_id_id__exact=trips[r["route_id"]][0].trip_id)
# stop_sequence[r["route_id"]] = [s for s in StopTime.objects.filter(trip_id_id__exact=trips[r["route_id"]].get(0).trip_id) if len(trips[r["route_id"]])]
#print(stop_sequences)
#print(trips[routes[0]["route_id"]][0])
#timetables = {r["route_id"]: {"stop_sequence": stop_sequences[r["route_id"]], "stop_times": {stop: sorted([st.departure_time for st in [StopTime.objects.filter(trip_id=t.trip_id.trip_id) for t in trips[r["route_id"]]]]) for stop in stop_sequences[r["route_id"]]}} for r in routes}
context = {"stops": stops, "routes": routes, }#"timetables": timetables}
return render(request,"map.html", context)