Got rid of bridge and fixed GTFS compliance
- Ported the bridge that was using a custom GTFS class and Pandas Dataframes to a native Django solution for and interface between db and csv (see api/io.py) - Fixed some issues regarding the compliance of the exported csv files with the GTFS reference. I.e. now allowing times 24:00:00 <= t >= 24:59:59
This commit is contained in:
parent
1494dba808
commit
f314bfb396
79
transport_accessibility/api/io.py
Normal file
79
transport_accessibility/api/io.py
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import csv
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
from pt_map.models import *
|
||||||
|
import pt_map
|
||||||
|
import pt_map.class_names
|
||||||
|
from django.db import models
|
||||||
|
import inspect
|
||||||
|
import datetime
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def csv_queryset(q: models.query.QuerySet) -> str:
|
||||||
|
fields = [field.name for field in q.model._meta.fields]
|
||||||
|
result = io.StringIO()
|
||||||
|
csv_writer = csv.DictWriter(result, fields)
|
||||||
|
csv_writer.writeheader()
|
||||||
|
|
||||||
|
for model in q:
|
||||||
|
row = {}
|
||||||
|
for field_name in fields:
|
||||||
|
field = model._meta.get_field(field_name)
|
||||||
|
value = model.__getattribute__(field.name)
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
if isinstance(field, models.DateField):
|
||||||
|
row[field.name] = value.strftime("%Y%m%d")
|
||||||
|
elif isinstance(field, models.ForeignKey):
|
||||||
|
row[field.name] = value.pk if not model == Shape else value.shape_id
|
||||||
|
elif isinstance(field, models.ManyToManyField):
|
||||||
|
row[field.name] = value.all().first().__getattribute__(field.name)
|
||||||
|
elif isinstance(field, models.BooleanField):
|
||||||
|
row[field.name] = int(value)
|
||||||
|
else:
|
||||||
|
row[field.name] = value
|
||||||
|
csv_writer.writerow(row)
|
||||||
|
return result.getvalue()
|
||||||
|
|
||||||
|
def models_csv(path: str) -> list[models.Model]:
|
||||||
|
assume_compliance = True
|
||||||
|
if assume_compliance:
|
||||||
|
os.chdir(path)
|
||||||
|
feed = None
|
||||||
|
order = []
|
||||||
|
for m in [*pt_map.class_names.fks.values(), *pt_map.class_names.mtm.values(), *[m for _,m in inspect.getmembers(pt_map.models, inspect.isclass)]]:
|
||||||
|
if m not in order:
|
||||||
|
order.append(m)
|
||||||
|
for m in order:
|
||||||
|
if os.path.exists(pt_map.class_names.file_names[m]):
|
||||||
|
with open(pt_map.class_names.file_names[m], 'r') as f:
|
||||||
|
csvreader = csv.DictReader(f)
|
||||||
|
mtm = {}
|
||||||
|
for row in csvreader:
|
||||||
|
for field in [field for field in m._meta.fields if field.name in csvreader.fieldnames]:
|
||||||
|
if not row[field.name]:
|
||||||
|
del row[field.name]
|
||||||
|
continue
|
||||||
|
if isinstance(field, models.ForeignKey):
|
||||||
|
row[field.name] = pt_map.class_names.fks[field.name].objects.get(pk=f"{feed.pk}_{row[field.name]}")
|
||||||
|
elif isinstance(field, models.DateField):
|
||||||
|
row[field.name] = datetime.datetime.fromisoformat(row[field.name])
|
||||||
|
elif (field.primary_key and feed) or field.name == 'service_id':
|
||||||
|
row[field.name] = f"{feed.pk}_{row[field.name]}"
|
||||||
|
for field in m._meta.many_to_many:
|
||||||
|
mtm[field.name] = pt_map.class_names.mtm[field.name].objects.filter(**{field.name: row[field.name]})
|
||||||
|
del row[field.name]
|
||||||
|
if feed:
|
||||||
|
row['feed_info_id'] = feed
|
||||||
|
if m == pt_map.models.Shape:
|
||||||
|
row['shape_id'] = f"{feed.pk}_{row['shape_id']}"
|
||||||
|
obj = m.objects.create(**row)
|
||||||
|
for name, value in mtm.items():
|
||||||
|
getattr(obj, name).set(value)
|
||||||
|
if not feed:
|
||||||
|
feed = obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -234,6 +234,7 @@ def db_to_gtfs(q: list[django.db.models.query.QuerySet], folder_path: str = ""):
|
||||||
object containing the queried data
|
object containing the queried data
|
||||||
"""
|
"""
|
||||||
dfs = {reversed_file_mapping[m.model.__name__]: (pd.DataFrame(list(m.values())) if m else pd.DataFrame()) for m in q}
|
dfs = {reversed_file_mapping[m.model.__name__]: (pd.DataFrame(list(m.values())) if m else pd.DataFrame()) for m in q}
|
||||||
|
dfs = {key: dfs[key].astype({col: pd.Timestamp for col in dfs[key].columns if isinstance(getattr(getattr(pt_map.models, {v:k for k,v in reversed_file_mapping.items()}[key]), col), django.db.models.DateField)}) for key in dfs.keys()}
|
||||||
g = pt_map.gtfs.GTFS(folder_path, dfs)
|
g = pt_map.gtfs.GTFS(folder_path, dfs)
|
||||||
g.validate()
|
g.validate()
|
||||||
return g
|
return g
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,40 @@ pt_map.models.Shape: "shapes",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file_names = {
|
||||||
|
pt_map.models.Agency: "agency.txt",
|
||||||
|
pt_map.models.Stop: "stops.txt",
|
||||||
|
pt_map.models.Route: "routes.txt",
|
||||||
|
pt_map.models.Trip: "trips.txt",
|
||||||
|
pt_map.models.StopTime: "stop_times.txt",
|
||||||
|
pt_map.models.Calendar: "calendar.txt",
|
||||||
|
pt_map.models.CalendarDate: "calendar_dates.txt",
|
||||||
|
pt_map.models.FareAttribute: "fare_attributes.txt",
|
||||||
|
pt_map.models.FareRule: "fare_rules.txt",
|
||||||
|
pt_map.models.Timeframe: "timeframes.txt",
|
||||||
|
pt_map.models.FareMedium: "fare_media.txt",
|
||||||
|
pt_map.models.FareProduct: "fare_products.txt",
|
||||||
|
pt_map.models.FareLegRule: "fare_leg_rules.txt",
|
||||||
|
pt_map.models.FareTransferRule: "fare_transfer_rules.txt",
|
||||||
|
pt_map.models.Area: "areas.txt",
|
||||||
|
pt_map.models.StopArea: "stop_areas.txt",
|
||||||
|
pt_map.models.Network: "networks.txt",
|
||||||
|
pt_map.models.RouteNetwork: "route_networks.txt",
|
||||||
|
pt_map.models.Shape: "shapes.txt",
|
||||||
|
pt_map.models.Frequency: "frequencies.txt",
|
||||||
|
pt_map.models.Transfer: "transfers.txt",
|
||||||
|
pt_map.models.Pathway: "pathways.txt",
|
||||||
|
pt_map.models.Level: "levels.txt",
|
||||||
|
pt_map.models.LocationGroup: "location_groups.txt",
|
||||||
|
pt_map.models.LocationGroupStop: "location_group_stops.txt",
|
||||||
|
pt_map.models.LocationsGeojson: "locations.geojson",
|
||||||
|
pt_map.models.BookingRule: "booking_rules.txt",
|
||||||
|
pt_map.models.Translation: "translations.txt",
|
||||||
|
pt_map.models.FeedInfo: "feed_info.txt",
|
||||||
|
pt_map.models.Attribution: "attributions.txt",
|
||||||
|
}
|
||||||
|
|
||||||
reversed_file_mapping = {
|
reversed_file_mapping = {
|
||||||
"Agency": "agency",
|
"Agency": "agency",
|
||||||
"Stop": "stops",
|
"Stop": "stops",
|
||||||
|
|
@ -276,4 +310,35 @@ foreign_keys = [
|
||||||
(pt_map.models.FareTransferRule, [(pt_map.models.FeedInfo, 'feed_info_id'),(pt_map.models.FareProduct, 'fare_product_id'), ]),
|
(pt_map.models.FareTransferRule, [(pt_map.models.FeedInfo, 'feed_info_id'),(pt_map.models.FareProduct, 'fare_product_id'), ]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
mtm = {
|
||||||
|
'shape_id': pt_map.models.Shape,
|
||||||
|
'from_timeframe_group_id': pt_map.models.Timeframe,
|
||||||
|
'to_timeframe_group_id': pt_map.models.Timeframe,
|
||||||
|
}
|
||||||
|
|
||||||
|
fks = {
|
||||||
|
'feed_info_id_id': pt_map.models.FeedInfo,
|
||||||
|
'parent_station': pt_map.models.Stop,
|
||||||
|
'level_id': pt_map.models.Level,
|
||||||
|
'agency_id': pt_map.models.Agency,
|
||||||
|
'route_id': pt_map.models.Route,
|
||||||
|
'trip_id': pt_map.models.Trip,
|
||||||
|
'stop_id': pt_map.models.Stop,
|
||||||
|
'location_group_id': pt_map.models.LocationGroup,
|
||||||
|
'location_id': pt_map.models.LocationsGeojson,
|
||||||
|
'fare_id': pt_map.models.FareAttribute,
|
||||||
|
'from_stop_id': pt_map.models.Stop,
|
||||||
|
'to_stop_id': pt_map.models.Stop,
|
||||||
|
'from_route_id': pt_map.models.Route,
|
||||||
|
'to_route_id': pt_map.models.Route,
|
||||||
|
'from_trip_id': pt_map.models.Trip,
|
||||||
|
'to_trip_id': pt_map.models.Trip,
|
||||||
|
'network_id': pt_map.models.Network,
|
||||||
|
'area_id': pt_map.models.Area,
|
||||||
|
'from_area_id': pt_map.models.Area,
|
||||||
|
'to_area_id': pt_map.models.Area,
|
||||||
|
'fare_product_id': pt_map.models.FareProduct,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fk_dict = {fk[0]: fk[1] for fk in foreign_keys}
|
fk_dict = {fk[0]: fk[1] for fk in foreign_keys}
|
||||||
|
|
|
||||||
|
|
@ -405,12 +405,13 @@ class GTFS:
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
for name in self.get_files():
|
for name in self.get_files():
|
||||||
df = getattr(self, name).data
|
df = getattr(self, name).data
|
||||||
|
df = df.astype({col: 'int8' for col in df.columns if df[col].dtype == 'bool'})
|
||||||
fpath = f"{path}/{name}.txt"
|
fpath = f"{path}/{name}.txt"
|
||||||
if name == 'locations_geojson':
|
if name == 'locations_geojson':
|
||||||
fpath = f"{path}/{name}.geojson"
|
fpath = f"{path}/{name}.geojson"
|
||||||
df.to_json(fpath)
|
df.to_json(fpath)
|
||||||
else:
|
else:
|
||||||
df.to_csv(fpath, index=False)
|
df.to_csv(fpath, date_format='%Y%m%d', index=False)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-06-22 09:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pt_map', '0003_faretransferrule_feed_info_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='trip',
|
||||||
|
name='shape_id',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='trip',
|
||||||
|
name='shape_id',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='shape', to='pt_map.shape'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-06-22 09:40
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pt_map', '0004_remove_trip_shape_id_trip_shape_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='trip',
|
||||||
|
name='shape_id',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='trips', to='pt_map.shape'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-06-23 20:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pt_map', '0005_alter_trip_shape_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bookingrule',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(blank=True, max_length=7, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bookingrule',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(blank=True, max_length=7, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='frequency',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='frequency',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stoptime',
|
||||||
|
name='arrival_time',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stoptime',
|
||||||
|
name='departure_time',
|
||||||
|
field=models.CharField(blank=True, max_length=7, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='timeframe',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='timeframe',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(max_length=7),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-06-23 21:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pt_map', '0006_alter_bookingrule_end_time_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bookingrule',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bookingrule',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='frequency',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='frequency',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stoptime',
|
||||||
|
name='departure_time',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='timeframe',
|
||||||
|
name='end_time',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='timeframe',
|
||||||
|
name='start_time',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-06-23 23:00
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pt_map', '0007_alter_bookingrule_end_time_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='timeframe',
|
||||||
|
name='service_id',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='trip',
|
||||||
|
name='service_id',
|
||||||
|
field=models.CharField(max_length=255),
|
||||||
|
),
|
||||||
|
]
|
||||||
600
transport_accessibility/pt_map/model_test_fields.py
Normal file
600
transport_accessibility/pt_map/model_test_fields.py
Normal file
|
|
@ -0,0 +1,600 @@
|
||||||
|
"""
|
||||||
|
Constants defining requirements of model fields.
|
||||||
|
To be used to decide wether a test should run or fail and which tests to run to test for self-preserved integrity.
|
||||||
|
"""
|
||||||
|
from pt_map.models import *
|
||||||
|
|
||||||
|
field_requirements = \
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"model": Agency,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "agency_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_url",
|
||||||
|
"type": "url",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_timezone",
|
||||||
|
"type": "timezone",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_lang",
|
||||||
|
"type": "langcode",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_phone",
|
||||||
|
"type": "telephone",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agency_email",
|
||||||
|
"type": "email",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Stop",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "stop_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_code",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_desc",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_lat",
|
||||||
|
"type": "float",
|
||||||
|
"required": "if",
|
||||||
|
"required_if": ["location_type", [0,1,2]],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_lon",
|
||||||
|
"type": "float",
|
||||||
|
"required": "if",
|
||||||
|
"required_if": ["location_type", [0,1,2]],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zone_id",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_url",
|
||||||
|
"type": "url",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "location_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parent_station",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "if",
|
||||||
|
"required_if": ["location_type", [2,3,4]],
|
||||||
|
"forbidden_if": ["location_type", [1]],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_timezone",
|
||||||
|
"type": "timezone",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wheelchair_boarding",
|
||||||
|
"type": "int",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Stop",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "stop_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_code",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_desc",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_lat",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_lon",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zone_id",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_url",
|
||||||
|
"type": "url",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "location_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parent_station",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_timezone",
|
||||||
|
"type": "timezone",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wheelchair_boarding",
|
||||||
|
"type": "int",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Route",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "route_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_short_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_long_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_desc",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_url",
|
||||||
|
"type": "url",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_color",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_text_color",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Trip",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "trip_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "service_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "trip_headsign",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "trip_short_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "direction_id",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "block_id",
|
||||||
|
"type": "str",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "StopTime",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "trip_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "arrival_time",
|
||||||
|
"type": "time",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "departure_time",
|
||||||
|
"type": "time",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stop_sequence",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pickup_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "drop_off_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_dist_traveled",
|
||||||
|
"type": "float",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timepoint",
|
||||||
|
"type": "int",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Calendar",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "service_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "monday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tuesday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wednesday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "thursday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "friday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "saturday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sunday",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "start_date",
|
||||||
|
"type": "date",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "end_date",
|
||||||
|
"type": "date",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "CalendarDates",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "service_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "date",
|
||||||
|
"type": "date",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "exception_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "FareAttributes",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "fare_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "price",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "currency_type",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "payment_method",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transfers",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transfer_duration",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "FareRules",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "fare_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "route_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "origin_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "destination_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "contains_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "FareZones",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "fare_zone_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zone_id",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Shape",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "shape_id",
|
||||||
|
"type": "pk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_pt_lat",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_pt_lon",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_pt_sequence",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shape_dist_traveled",
|
||||||
|
"type": "float",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Frequencies",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "trip_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "start_time",
|
||||||
|
"type": "time",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "end_time",
|
||||||
|
"type": "time",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "headway_secs",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "exact_times",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Transfers",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "from_stop_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "to_stop_id",
|
||||||
|
"type": "fk",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "transfer_type",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_transfer_time",
|
||||||
|
"type": "int",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "FeedInfo",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "feed_publisher_name",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "feed_publisher_url",
|
||||||
|
"type": "url",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "feed_lang",
|
||||||
|
"type": "langcode",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "feed_start_date",
|
||||||
|
"type": "date",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "feed_end_date",
|
||||||
|
"type": "date",
|
||||||
|
"required": "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "feed_version",
|
||||||
|
"type": "str",
|
||||||
|
"required": "true",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
@ -139,12 +139,12 @@ class Trip(models.Model):
|
||||||
"""
|
"""
|
||||||
trip_id = models.CharField(max_length=255, primary_key=True)
|
trip_id = models.CharField(max_length=255, primary_key=True)
|
||||||
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
|
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
|
||||||
service_id = models.IntegerField()
|
service_id = models.CharField(max_length=255)
|
||||||
trip_headsign = models.CharField(max_length=255, blank=True, null=True)
|
trip_headsign = models.CharField(max_length=255, blank=True, null=True)
|
||||||
trip_short_name = 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)
|
direction_id = models.IntegerField(blank=True, null=True)
|
||||||
block_id = models.CharField(max_length=255, 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)
|
shape_id = models.ManyToManyField(Shape, related_name='trips', blank=True)
|
||||||
wheelchair_accessible = models.IntegerField(blank=True, null=True)
|
wheelchair_accessible = models.IntegerField(blank=True, null=True)
|
||||||
bikes_allowed = models.IntegerField(blank=True, null=True)
|
bikes_allowed = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
|
@ -191,8 +191,8 @@ class StopTime(models.Model):
|
||||||
"""
|
"""
|
||||||
stop_time_id = models.BigAutoField(primary_key=True)
|
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.CharField(max_length=255, blank=True, null=True)
|
||||||
departure_time = models.TimeField(blank=True, null=True)
|
departure_time = models.CharField(max_length=255, blank=True, null=True)
|
||||||
stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
|
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_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)
|
location_id = models.ForeignKey(LocationsGeojson, on_delete=models.SET_NULL, blank=True, null=True)
|
||||||
|
|
@ -238,8 +238,8 @@ class Frequency(models.Model):
|
||||||
"""
|
"""
|
||||||
frequency_id = models.BigAutoField(primary_key=True)
|
frequency_id = models.BigAutoField(primary_key=True)
|
||||||
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
|
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
|
||||||
start_time = models.TimeField()
|
start_time = models.CharField(max_length=255)
|
||||||
end_time = models.TimeField()
|
end_time = models.CharField(max_length=255)
|
||||||
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(FeedInfo, on_delete=models.CASCADE)
|
feed_info_id = models.ForeignKey(FeedInfo, on_delete=models.CASCADE)
|
||||||
|
|
@ -286,8 +286,8 @@ class BookingRule(models.Model):
|
||||||
"""
|
"""
|
||||||
booking_rule_id = models.CharField(max_length=255, primary_key=True)
|
booking_rule_id = models.CharField(max_length=255, primary_key=True)
|
||||||
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
|
trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
|
||||||
start_time = models.TimeField(blank=True, null=True)
|
start_time = models.CharField(max_length=255, blank=True, null=True)
|
||||||
end_time = models.TimeField(blank=True, null=True)
|
end_time = models.CharField(max_length=255, blank=True, null=True)
|
||||||
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)
|
||||||
|
|
@ -390,11 +390,11 @@ class Timeframe(models.Model):
|
||||||
Represents timeframe.txt from the GTFS Reference.
|
Represents timeframe.txt from the GTFS Reference.
|
||||||
"""
|
"""
|
||||||
timeframe_group_id = models.CharField(max_length=255,primary_key=True)
|
timeframe_group_id = models.CharField(max_length=255,primary_key=True)
|
||||||
service_id = models.IntegerField()
|
service_id = models.CharField(max_length=255)
|
||||||
start_date = models.DateField()
|
start_date = models.DateField()
|
||||||
end_date = models.DateField()
|
end_date = models.DateField()
|
||||||
start_time = models.TimeField()
|
start_time = models.CharField(max_length=255)
|
||||||
end_time = models.TimeField()
|
end_time = models.CharField(max_length=255)
|
||||||
feed_info_id = models.ForeignKey(FeedInfo, on_delete=models.CASCADE)
|
feed_info_id = models.ForeignKey(FeedInfo, on_delete=models.CASCADE)
|
||||||
|
|
||||||
class FareLegRule(models.Model):
|
class FareLegRule(models.Model):
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,26 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from pt_map.models import Agency, FeedInfo, Level, Stop, Route, Shape, Calendar, CalendarDate, LocationGroup, LocationGroupStop, LocationsGeojson, Trip, StopArea, StopTime, FareAttribute, FareLegRule, FareMedium, FareProduct, FareTransferRule, FareRule, Frequency, Transfer, Pathway, BookingRule, Translation, Attribution, Network, RouteNetwork, Area, Timeframe
|
||||||
|
from datetime import date, datetime
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
class FeedInfoTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
FeedInfo.objects.create(feed_publisher_name="All fields", feed_publisher_url='example.com', feed_lang='pl', default_lang='pl', feed_start_date=datetime(2024, 1, 1), feed_end_date=datetime.now(), feed_version='1.0', feed_contact_email='me@example.com', feed_contact_url='example.com')
|
||||||
|
def test_ok(self):
|
||||||
|
FeedInfo.objects.get(feed_publisher_name="All fields")
|
||||||
|
FeedInfo.objects.get(feed_publisher_url='example.com')
|
||||||
|
FeedInfo.objects.get(feed_lang='pl')
|
||||||
|
FeedInfo.objects.get(default_lang='pl')
|
||||||
|
FeedInfo.objects.get(feed_start_date=datetime(2024, 1, 1))
|
||||||
|
FeedInfo.objects.get(feed_end_date=datetime.now())
|
||||||
|
FeedInfo.objects.get(feed_version='1.0')
|
||||||
|
FeedInfo.objects.get(feed_contact_email='me@example.com')
|
||||||
|
FeedInfo.objects.get(feed_contact_email='me@example.com')
|
||||||
|
|
||||||
|
|
||||||
|
class AgencyTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
FeedInfo.objects.create(feed_publisher_name="All fields", feed_publisher_url='example.com', feed_lang='pl', default_lang='pl', feed_start_date=datetime(2024, 1, 1), feed_end_date=datetime.now(), feed_version='1.0', feed_contact_email='me@example.com', feed_contact_url='example.com')
|
||||||
|
Agency.objects.create(agency_name='test', agency_url='example.com', agency_timezone='Europe/Berlin', agency_lang='pl', agency_phone='0123456574', agency_fare_url='example.com', agency_email='me@example.com', feed_info_id=FeedInfo.objects.get(feed_publisher_name="All fields"))
|
||||||
|
def test_ok(self):
|
||||||
|
print(Agency.objects.get(agency_name='test').feed_info_id.feed_id)
|
||||||
|
|
|
||||||
10
transport_accessibility/test.py
Normal file
10
transport_accessibility/test.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import pt_map.models
|
||||||
|
import api.io
|
||||||
|
import inspect
|
||||||
|
#api.io.models_csv("/home/johannes/Downloads/torun")
|
||||||
|
q = [m.objects.all() for _,m in inspect.getmembers(pt_map.models, inspect.isclass)]
|
||||||
|
for s in q:
|
||||||
|
f = f"/home/johannes/Downloads/test3/{pt_map.class_names.case_swap[s.model._meta.object_name]}.txt"
|
||||||
|
with open(f, 'w') as file:
|
||||||
|
file.write(api.io.csv_queryset(s))
|
||||||
|
quit()
|
||||||
Loading…
Reference in New Issue
Block a user