Truncate trip id
This commit is contained in:
parent
8d2ffe3014
commit
77c3ef9e74
|
@ -4,6 +4,37 @@ from sncfgtfs.models import Agency, Stop, Route, Trip, StopTime, Calendar, Calen
|
||||||
Transfer, FeedInfo, StopTimeUpdate, TripUpdate
|
Transfer, FeedInfo, StopTimeUpdate, TripUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarDateInline(admin.TabularInline):
|
||||||
|
model = CalendarDate
|
||||||
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
|
class TripInline(admin.TabularInline):
|
||||||
|
model = Trip
|
||||||
|
extra = 0
|
||||||
|
autocomplete_fields = ('route', 'service',)
|
||||||
|
show_change_link = True
|
||||||
|
ordering = ('service',)
|
||||||
|
|
||||||
|
|
||||||
|
class StopTimeInline(admin.TabularInline):
|
||||||
|
model = StopTime
|
||||||
|
extra = 0
|
||||||
|
autocomplete_fields = ('stop',)
|
||||||
|
show_change_link = True
|
||||||
|
ordering = ('stop_sequence',)
|
||||||
|
|
||||||
|
|
||||||
|
class TripUpdateInline(admin.StackedInline):
|
||||||
|
model = TripUpdate
|
||||||
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
|
class StopTimeUpdateInline(admin.StackedInline):
|
||||||
|
model = StopTimeUpdate
|
||||||
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Agency)
|
@admin.register(Agency)
|
||||||
class AgencyAdmin(admin.ModelAdmin):
|
class AgencyAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'id', 'url', 'timezone',)
|
list_display = ('name', 'id', 'url', 'timezone',)
|
||||||
|
@ -26,24 +57,28 @@ class RouteAdmin(admin.ModelAdmin):
|
||||||
search_fields = ('long_name', 'short_name', 'id',)
|
search_fields = ('long_name', 'short_name', 'id',)
|
||||||
ordering = ('long_name',)
|
ordering = ('long_name',)
|
||||||
autocomplete_fields = ('agency',)
|
autocomplete_fields = ('agency',)
|
||||||
|
inlines = (TripInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Trip)
|
@admin.register(Trip)
|
||||||
class TripAdmin(admin.ModelAdmin):
|
class TripAdmin(admin.ModelAdmin):
|
||||||
list_display = ('id', 'route', 'service', 'headsign', 'direction_id',)
|
list_display = ('id', 'route', 'service', 'headsign', 'direction_id',)
|
||||||
list_filter = ('direction_id', 'service__transport_type',)
|
list_filter = ('direction_id', 'route__transport_type',)
|
||||||
search_fields = ('id', 'route__id', 'route__long_name', 'service__id', 'headsign',)
|
search_fields = ('id', 'route__id', 'route__long_name', 'service__id', 'headsign',)
|
||||||
ordering = ('route', 'service',)
|
ordering = ('route', 'service',)
|
||||||
|
autocomplete_fields = ('route', 'service',)
|
||||||
|
inlines = (StopTimeInline, TripUpdateInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(StopTime)
|
@admin.register(StopTime)
|
||||||
class StopTimeAdmin(admin.ModelAdmin):
|
class StopTimeAdmin(admin.ModelAdmin):
|
||||||
list_display = ('trip', 'stop', 'arrival_time', 'departure_time',
|
list_display = ('trip', 'stop', 'arrival_time', 'departure_time',
|
||||||
'stop_sequence', 'pickup_type', 'drop_off_type',)
|
'stop_sequence', 'pickup_type', 'drop_off_type',)
|
||||||
list_filter = ('pickup_type', 'drop_off_type', 'trip__service__transport_type',)
|
list_filter = ('pickup_type', 'drop_off_type', 'trip__route__transport_type',)
|
||||||
search_fields = ('trip__id', 'stop__name', 'arrival_time', 'departure_time',)
|
search_fields = ('trip__id', 'stop__name', 'arrival_time', 'departure_time',)
|
||||||
ordering = ('trip', 'stop_sequence',)
|
ordering = ('trip', 'stop_sequence',)
|
||||||
autocomplete_fields = ('trip', 'stop',)
|
autocomplete_fields = ('trip', 'stop',)
|
||||||
|
inlines = (StopTimeUpdateInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Calendar)
|
@admin.register(Calendar)
|
||||||
|
@ -54,6 +89,7 @@ class CalendarAdmin(admin.ModelAdmin):
|
||||||
'start_date', 'end_date',)
|
'start_date', 'end_date',)
|
||||||
search_fields = ('id', 'start_date', 'end_date',)
|
search_fields = ('id', 'start_date', 'end_date',)
|
||||||
ordering = ('transport_type', 'id',)
|
ordering = ('transport_type', 'id',)
|
||||||
|
inlines = (CalendarDateInline, TripInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(CalendarDate)
|
@admin.register(CalendarDate)
|
||||||
|
|
|
@ -20,10 +20,17 @@ class Command(BaseCommand):
|
||||||
}
|
}
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('--bulk_size', type=int, default=1000, help='Number of objects to create in bulk.')
|
parser.add_argument('--bulk_size', type=int, default=1000, help="Number of objects to create in bulk.")
|
||||||
|
parser.add_argument('--dry-run', action='store_true',
|
||||||
|
help="Do not update the database, only print what would be done.")
|
||||||
|
parser.add_argument('--force', '-f', action='store_true', help="Force the update of the database.")
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
bulk_size = options['bulk_size']
|
bulk_size = options['bulk_size']
|
||||||
|
dry_run = options['dry_run']
|
||||||
|
force = options['force']
|
||||||
|
if dry_run:
|
||||||
|
self.stdout.write(self.style.WARNING("Dry run mode activated."))
|
||||||
|
|
||||||
if not FeedInfo.objects.exists():
|
if not FeedInfo.objects.exists():
|
||||||
last_update_date = "1970-01-01"
|
last_update_date = "1970-01-01"
|
||||||
|
@ -36,11 +43,14 @@ class Command(BaseCommand):
|
||||||
if last_modified.date().isoformat() > last_update_date:
|
if last_modified.date().isoformat() > last_update_date:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
if not force:
|
||||||
self.stdout.write(self.style.WARNING("Database already up-to-date."))
|
self.stdout.write(self.style.WARNING("Database already up-to-date."))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.stdout.write("Updating database...")
|
self.stdout.write("Updating database...")
|
||||||
|
|
||||||
|
all_trips = []
|
||||||
|
|
||||||
for transport_type, feed_url in self.GTFS_FEEDS.items():
|
for transport_type, feed_url in self.GTFS_FEEDS.items():
|
||||||
self.stdout.write(f"Downloading {transport_type} GTFS feed...")
|
self.stdout.write(f"Downloading {transport_type} GTFS feed...")
|
||||||
with ZipFile(BytesIO(requests.get(feed_url).content)) as zipfile:
|
with ZipFile(BytesIO(requests.get(feed_url).content)) as zipfile:
|
||||||
|
@ -57,7 +67,7 @@ class Command(BaseCommand):
|
||||||
email=agency_dict.get('agency_email', ""),
|
email=agency_dict.get('agency_email', ""),
|
||||||
)
|
)
|
||||||
agencies.append(agency)
|
agencies.append(agency)
|
||||||
if agencies:
|
if agencies and not dry_run:
|
||||||
Agency.objects.bulk_create(agencies,
|
Agency.objects.bulk_create(agencies,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['name', 'url', 'timezone', 'lang', 'phone', 'email'],
|
update_fields=['name', 'url', 'timezone', 'lang', 'phone', 'email'],
|
||||||
|
@ -85,7 +95,7 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
stops.append(stop)
|
stops.append(stop)
|
||||||
|
|
||||||
if len(stops) >= bulk_size:
|
if len(stops) >= bulk_size and not dry_run:
|
||||||
Stop.objects.bulk_create(stops,
|
Stop.objects.bulk_create(stops,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['name', 'desc', 'lat', 'lon', 'zone_id', 'url',
|
update_fields=['name', 'desc', 'lat', 'lon', 'zone_id', 'url',
|
||||||
|
@ -93,7 +103,7 @@ class Command(BaseCommand):
|
||||||
'wheelchair_boarding', 'level_id', 'platform_code'],
|
'wheelchair_boarding', 'level_id', 'platform_code'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
stops.clear()
|
stops.clear()
|
||||||
if stops:
|
if stops and not dry_run:
|
||||||
Stop.objects.bulk_create(stops,
|
Stop.objects.bulk_create(stops,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['name', 'desc', 'lat', 'lon', 'zone_id', 'url',
|
update_fields=['name', 'desc', 'lat', 'lon', 'zone_id', 'url',
|
||||||
|
@ -115,17 +125,19 @@ class Command(BaseCommand):
|
||||||
url=route_dict['route_url'],
|
url=route_dict['route_url'],
|
||||||
color=route_dict['route_color'],
|
color=route_dict['route_color'],
|
||||||
text_color=route_dict['route_text_color'],
|
text_color=route_dict['route_text_color'],
|
||||||
|
transport_type=transport_type,
|
||||||
)
|
)
|
||||||
routes.append(route)
|
routes.append(route)
|
||||||
|
|
||||||
if len(routes) >= bulk_size:
|
if len(routes) >= bulk_size and not dry_run:
|
||||||
Route.objects.bulk_create(routes,
|
Route.objects.bulk_create(routes,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['agency_id', 'short_name', 'long_name', 'desc',
|
update_fields=['agency_id', 'short_name', 'long_name', 'desc',
|
||||||
'type', 'url', 'color', 'text_color'],
|
'type', 'url', 'color', 'text_color',
|
||||||
|
'transport_type'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
routes.clear()
|
routes.clear()
|
||||||
if routes:
|
if routes and not dry_run:
|
||||||
Route.objects.bulk_create(routes,
|
Route.objects.bulk_create(routes,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['agency_id', 'short_name', 'long_name', 'desc',
|
update_fields=['agency_id', 'short_name', 'long_name', 'desc',
|
||||||
|
@ -154,7 +166,7 @@ class Command(BaseCommand):
|
||||||
calendars.append(calendar)
|
calendars.append(calendar)
|
||||||
calendar_ids.append(calendar.id)
|
calendar_ids.append(calendar.id)
|
||||||
|
|
||||||
if len(calendars) >= bulk_size:
|
if len(calendars) >= bulk_size and not dry_run:
|
||||||
Calendar.objects.bulk_create(calendars,
|
Calendar.objects.bulk_create(calendars,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['monday', 'tuesday', 'wednesday', 'thursday',
|
update_fields=['monday', 'tuesday', 'wednesday', 'thursday',
|
||||||
|
@ -162,7 +174,7 @@ class Command(BaseCommand):
|
||||||
'end_date', 'transport_type'],
|
'end_date', 'transport_type'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
calendars.clear()
|
calendars.clear()
|
||||||
if calendars:
|
if calendars and not dry_run:
|
||||||
Calendar.objects.bulk_create(calendars, update_conflicts=True,
|
Calendar.objects.bulk_create(calendars, update_conflicts=True,
|
||||||
update_fields=['monday', 'tuesday', 'wednesday', 'thursday',
|
update_fields=['monday', 'tuesday', 'wednesday', 'thursday',
|
||||||
'friday', 'saturday', 'sunday', 'start_date',
|
'friday', 'saturday', 'sunday', 'start_date',
|
||||||
|
@ -198,7 +210,7 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
calendars.append(calendar)
|
calendars.append(calendar)
|
||||||
|
|
||||||
if len(calendar_dates) >= bulk_size:
|
if len(calendar_dates) >= bulk_size and not dry_run:
|
||||||
Calendar.objects.bulk_create(calendars,
|
Calendar.objects.bulk_create(calendars,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['end_date'],
|
update_fields=['end_date'],
|
||||||
|
@ -210,7 +222,7 @@ class Command(BaseCommand):
|
||||||
calendars.clear()
|
calendars.clear()
|
||||||
calendar_dates.clear()
|
calendar_dates.clear()
|
||||||
|
|
||||||
if calendar_dates:
|
if calendar_dates and not dry_run:
|
||||||
Calendar.objects.bulk_create(calendars,
|
Calendar.objects.bulk_create(calendars,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['end_date'],
|
update_fields=['end_date'],
|
||||||
|
@ -225,8 +237,14 @@ class Command(BaseCommand):
|
||||||
trips = []
|
trips = []
|
||||||
for trip_dict in csv.DictReader(zipfile.read("trips.txt").decode().splitlines()):
|
for trip_dict in csv.DictReader(zipfile.read("trips.txt").decode().splitlines()):
|
||||||
trip_dict: dict
|
trip_dict: dict
|
||||||
|
trip_id = trip_dict['trip_id']
|
||||||
|
if transport_type != "TN":
|
||||||
|
trip_id, last_update = trip_id.split(':', 1)
|
||||||
|
last_update = datetime.fromisoformat(last_update)
|
||||||
|
else:
|
||||||
|
last_update = None
|
||||||
trip = Trip(
|
trip = Trip(
|
||||||
id=trip_dict['trip_id'],
|
id=trip_id,
|
||||||
route_id=trip_dict['route_id'],
|
route_id=trip_dict['route_id'],
|
||||||
service_id=f"{transport_type}-{trip_dict['service_id']}",
|
service_id=f"{transport_type}-{trip_dict['service_id']}",
|
||||||
headsign=trip_dict['trip_headsign'],
|
headsign=trip_dict['trip_headsign'],
|
||||||
|
@ -236,10 +254,11 @@ class Command(BaseCommand):
|
||||||
shape_id=trip_dict['shape_id'],
|
shape_id=trip_dict['shape_id'],
|
||||||
wheelchair_accessible=trip_dict.get('wheelchair_accessible', None),
|
wheelchair_accessible=trip_dict.get('wheelchair_accessible', None),
|
||||||
bikes_allowed=trip_dict.get('bikes_allowed', None),
|
bikes_allowed=trip_dict.get('bikes_allowed', None),
|
||||||
|
last_update=last_update,
|
||||||
)
|
)
|
||||||
trips.append(trip)
|
trips.append(trip)
|
||||||
|
|
||||||
if len(trips) >= bulk_size:
|
if len(trips) >= bulk_size and not dry_run:
|
||||||
Trip.objects.bulk_create(trips,
|
Trip.objects.bulk_create(trips,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['route_id', 'service_id', 'headsign', 'short_name',
|
update_fields=['route_id', 'service_id', 'headsign', 'short_name',
|
||||||
|
@ -247,7 +266,7 @@ class Command(BaseCommand):
|
||||||
'wheelchair_accessible', 'bikes_allowed'],
|
'wheelchair_accessible', 'bikes_allowed'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
trips.clear()
|
trips.clear()
|
||||||
if trips:
|
if trips and not dry_run:
|
||||||
Trip.objects.bulk_create(trips,
|
Trip.objects.bulk_create(trips,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['route_id', 'service_id', 'headsign', 'short_name',
|
update_fields=['route_id', 'service_id', 'headsign', 'short_name',
|
||||||
|
@ -256,17 +275,22 @@ class Command(BaseCommand):
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
trips.clear()
|
trips.clear()
|
||||||
|
|
||||||
|
all_trips.extend(trips)
|
||||||
|
|
||||||
stop_times = []
|
stop_times = []
|
||||||
for stop_time_dict in csv.DictReader(zipfile.read("stop_times.txt").decode().splitlines()):
|
for stop_time_dict in csv.DictReader(zipfile.read("stop_times.txt").decode().splitlines()):
|
||||||
stop_time_dict: dict
|
stop_time_dict: dict
|
||||||
|
|
||||||
|
trip_id = stop_time_dict['trip_id']
|
||||||
|
if transport_type != "TN":
|
||||||
|
trip_id = trip_id.split(':', 1)[0]
|
||||||
arr_time = stop_time_dict['arrival_time']
|
arr_time = stop_time_dict['arrival_time']
|
||||||
arr_time = int(arr_time[:2]) * 3600 + int(arr_time[3:5]) * 60 + int(arr_time[6:])
|
arr_time = int(arr_time[:2]) * 3600 + int(arr_time[3:5]) * 60 + int(arr_time[6:])
|
||||||
dep_time = stop_time_dict['departure_time']
|
dep_time = stop_time_dict['departure_time']
|
||||||
dep_time = int(dep_time[:2]) * 3600 + int(dep_time[3:5]) * 60 + int(dep_time[6:])
|
dep_time = int(dep_time[:2]) * 3600 + int(dep_time[3:5]) * 60 + int(dep_time[6:])
|
||||||
st = StopTime(
|
st = StopTime(
|
||||||
id=f"{stop_time_dict['trip_id']}-{stop_time_dict['stop_id']}",
|
id=f"{stop_time_dict['trip_id']}-{stop_time_dict['stop_id']}",
|
||||||
trip_id=stop_time_dict['trip_id'],
|
trip_id=trip_id,
|
||||||
arrival_time=timedelta(seconds=arr_time),
|
arrival_time=timedelta(seconds=arr_time),
|
||||||
departure_time=timedelta(seconds=dep_time),
|
departure_time=timedelta(seconds=dep_time),
|
||||||
stop_id=stop_time_dict['stop_id'],
|
stop_id=stop_time_dict['stop_id'],
|
||||||
|
@ -278,7 +302,7 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
stop_times.append(st)
|
stop_times.append(st)
|
||||||
|
|
||||||
if len(stop_times) >= bulk_size:
|
if len(stop_times) >= bulk_size and not dry_run:
|
||||||
StopTime.objects.bulk_create(stop_times,
|
StopTime.objects.bulk_create(stop_times,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['stop_id', 'arrival_time', 'departure_time',
|
update_fields=['stop_id', 'arrival_time', 'departure_time',
|
||||||
|
@ -286,7 +310,7 @@ class Command(BaseCommand):
|
||||||
'drop_off_type', 'timepoint'],
|
'drop_off_type', 'timepoint'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
stop_times.clear()
|
stop_times.clear()
|
||||||
if stop_times:
|
if stop_times and not dry_run:
|
||||||
StopTime.objects.bulk_create(stop_times,
|
StopTime.objects.bulk_create(stop_times,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['stop_id', 'arrival_time', 'departure_time',
|
update_fields=['stop_id', 'arrival_time', 'departure_time',
|
||||||
|
@ -307,21 +331,21 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
transfers.append(transfer)
|
transfers.append(transfer)
|
||||||
|
|
||||||
if len(transfers) >= bulk_size:
|
if len(transfers) >= bulk_size and not dry_run:
|
||||||
Transfer.objects.bulk_create(transfers,
|
Transfer.objects.bulk_create(transfers,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['transfer_type', 'min_transfer_time'],
|
update_fields=['transfer_type', 'min_transfer_time'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
transfers.clear()
|
transfers.clear()
|
||||||
|
|
||||||
if transfers:
|
if transfers and not dry_run:
|
||||||
Transfer.objects.bulk_create(transfers,
|
Transfer.objects.bulk_create(transfers,
|
||||||
update_conflicts=True,
|
update_conflicts=True,
|
||||||
update_fields=['transfer_type', 'min_transfer_time'],
|
update_fields=['transfer_type', 'min_transfer_time'],
|
||||||
unique_fields=['id'])
|
unique_fields=['id'])
|
||||||
transfers.clear()
|
transfers.clear()
|
||||||
|
|
||||||
if "feed_info.txt" in zipfile.namelist():
|
if "feed_info.txt" in zipfile.namelist() and not dry_run:
|
||||||
for feed_info_dict in csv.DictReader(zipfile.read("feed_info.txt").decode().splitlines()):
|
for feed_info_dict in csv.DictReader(zipfile.read("feed_info.txt").decode().splitlines()):
|
||||||
feed_info_dict: dict
|
feed_info_dict: dict
|
||||||
FeedInfo.objects.update_or_create(
|
FeedInfo.objects.update_or_create(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-27 14:08
|
# Generated by Django 5.0.1 on 2024-02-09 21:55
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -155,19 +155,6 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="Exception type",
|
verbose_name="Exception type",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"transport_type",
|
|
||||||
models.CharField(
|
|
||||||
choices=[
|
|
||||||
("TGV", "TGV"),
|
|
||||||
("TER", "TER"),
|
|
||||||
("IC", "Intercités"),
|
|
||||||
("TN", "Transilien"),
|
|
||||||
],
|
|
||||||
max_length=255,
|
|
||||||
verbose_name="Transport type",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"service",
|
"service",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
@ -239,13 +226,26 @@ class Migration(migrations.Migration):
|
||||||
blank=True, max_length=255, verbose_name="Route text color"
|
blank=True, max_length=255, verbose_name="Route text color"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"transport_type",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("TGV", "TGV"),
|
||||||
|
("TER", "TER"),
|
||||||
|
("IC", "Intercités"),
|
||||||
|
("TN", "Transilien"),
|
||||||
|
],
|
||||||
|
max_length=255,
|
||||||
|
verbose_name="Transport type",
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"agency",
|
"agency",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
related_name="routes",
|
related_name="routes",
|
||||||
to="sncfgtfs.agency",
|
to="sncfgtfs.agency",
|
||||||
verbose_name="Agency ID",
|
verbose_name="Agency",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -474,6 +474,10 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="Bikes allowed",
|
verbose_name="Bikes allowed",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"last_update",
|
||||||
|
models.DateTimeField(null=True, verbose_name="Last update"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"route",
|
"route",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
@ -496,7 +500,6 @@ class Migration(migrations.Migration):
|
||||||
options={
|
options={
|
||||||
"verbose_name": "Trip",
|
"verbose_name": "Trip",
|
||||||
"verbose_name_plural": "Trips",
|
"verbose_name_plural": "Trips",
|
||||||
"ordering": ("id",),
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
@ -578,4 +581,95 @@ class Migration(migrations.Migration):
|
||||||
"verbose_name_plural": "Stop times",
|
"verbose_name_plural": "Stop times",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="TripUpdate",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"trip",
|
||||||
|
models.OneToOneField(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
primary_key=True,
|
||||||
|
related_name="update",
|
||||||
|
serialize=False,
|
||||||
|
to="sncfgtfs.trip",
|
||||||
|
verbose_name="Trip",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("start_date", models.DateField(verbose_name="Start date")),
|
||||||
|
("start_time", models.TimeField(verbose_name="Start time")),
|
||||||
|
(
|
||||||
|
"schedule_relationship",
|
||||||
|
models.IntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Scheduled"),
|
||||||
|
(1, "Added"),
|
||||||
|
(2, "Unscheduled"),
|
||||||
|
(3, "Canceled"),
|
||||||
|
(5, "Replacement"),
|
||||||
|
(6, "Duplicated"),
|
||||||
|
(7, "Deleted"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
verbose_name="Schedule relationship",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Trip update",
|
||||||
|
"verbose_name_plural": "Trip updates",
|
||||||
|
"ordering": ("start_date", "trip"),
|
||||||
|
"unique_together": {("trip", "start_date", "start_time")},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="StopTimeUpdate",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"stop_time",
|
||||||
|
models.OneToOneField(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
primary_key=True,
|
||||||
|
related_name="update",
|
||||||
|
serialize=False,
|
||||||
|
to="sncfgtfs.stoptime",
|
||||||
|
verbose_name="Stop time",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("arrival_delay", models.DurationField(verbose_name="Arrival delay")),
|
||||||
|
("arrival_time", models.DateTimeField(verbose_name="Arrival time")),
|
||||||
|
(
|
||||||
|
"departure_delay",
|
||||||
|
models.DurationField(verbose_name="Departure delay"),
|
||||||
|
),
|
||||||
|
("departure_time", models.DateTimeField(verbose_name="Departure time")),
|
||||||
|
(
|
||||||
|
"schedule_relationship",
|
||||||
|
models.IntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Scheduled"),
|
||||||
|
(1, "Skipped"),
|
||||||
|
(2, "No data"),
|
||||||
|
(3, "Unscheduled"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
verbose_name="Schedule relationship",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"trip_update",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="stop_time_updates",
|
||||||
|
to="sncfgtfs.tripupdate",
|
||||||
|
verbose_name="Trip update",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Stop time update",
|
||||||
|
"verbose_name_plural": "Stop time updates",
|
||||||
|
"ordering": ("trip_update", "stop_time"),
|
||||||
|
"unique_together": {("trip_update", "stop_time")},
|
||||||
|
},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-02-06 06:59
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("sncfgtfs", "0001_initial"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterModelOptions(
|
|
||||||
name="trip",
|
|
||||||
options={"verbose_name": "Trip", "verbose_name_plural": "Trips"},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="TripUpdate",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"trip",
|
|
||||||
models.OneToOneField(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
primary_key=True,
|
|
||||||
related_name="update",
|
|
||||||
serialize=False,
|
|
||||||
to="sncfgtfs.trip",
|
|
||||||
verbose_name="Trip",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("start_date", models.DateField(verbose_name="Start date")),
|
|
||||||
("start_time", models.TimeField(verbose_name="Start time")),
|
|
||||||
(
|
|
||||||
"schedule_relationship",
|
|
||||||
models.IntegerField(
|
|
||||||
choices=[
|
|
||||||
(0, "Scheduled"),
|
|
||||||
(1, "Added"),
|
|
||||||
(2, "Unscheduled"),
|
|
||||||
(3, "Canceled"),
|
|
||||||
(5, "Replacement"),
|
|
||||||
(6, "Duplicated"),
|
|
||||||
(7, "Deleted"),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
verbose_name="Schedule relationship",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Trip update",
|
|
||||||
"verbose_name_plural": "Trip updates",
|
|
||||||
"ordering": ("start_date", "trip"),
|
|
||||||
"unique_together": {("trip", "start_date", "start_time")},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="StopTimeUpdate",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"stop_time",
|
|
||||||
models.OneToOneField(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
primary_key=True,
|
|
||||||
related_name="update",
|
|
||||||
serialize=False,
|
|
||||||
to="sncfgtfs.stoptime",
|
|
||||||
verbose_name="Stop time",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("arrival_delay", models.DurationField(verbose_name="Arrival delay")),
|
|
||||||
("arrival_time", models.DateTimeField(verbose_name="Arrival time")),
|
|
||||||
(
|
|
||||||
"departure_delay",
|
|
||||||
models.DurationField(verbose_name="Departure delay"),
|
|
||||||
),
|
|
||||||
("departure_time", models.DateTimeField(verbose_name="Departure time")),
|
|
||||||
(
|
|
||||||
"schedule_relationship",
|
|
||||||
models.IntegerField(
|
|
||||||
choices=[
|
|
||||||
(0, "Scheduled"),
|
|
||||||
(1, "Skipped"),
|
|
||||||
(2, "No data"),
|
|
||||||
(3, "Unscheduled"),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
verbose_name="Schedule relationship",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"trip_update",
|
|
||||||
models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
related_name="stop_time_updates",
|
|
||||||
to="sncfgtfs.tripupdate",
|
|
||||||
verbose_name="Trip update",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Stop time update",
|
|
||||||
"verbose_name_plural": "Stop time updates",
|
|
||||||
"ordering": ("trip_update", "stop_time"),
|
|
||||||
"unique_together": {("trip_update", "stop_time")},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -230,7 +230,7 @@ class Route(models.Model):
|
||||||
agency = models.ForeignKey(
|
agency = models.ForeignKey(
|
||||||
to="Agency",
|
to="Agency",
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
verbose_name=_("Agency ID"),
|
verbose_name=_("Agency"),
|
||||||
related_name="routes",
|
related_name="routes",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -272,6 +272,12 @@ class Route(models.Model):
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
transport_type = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("Transport type"),
|
||||||
|
choices=TransportType,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.long_name}"
|
return f"{self.long_name}"
|
||||||
|
|
||||||
|
@ -346,6 +352,11 @@ class Trip(models.Model):
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
last_update = models.DateTimeField(
|
||||||
|
verbose_name=_("Last update"),
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def origin(self):
|
def origin(self):
|
||||||
return self.stop_times.order_by('stop_sequence').first().stop
|
return self.stop_times.order_by('stop_sequence').first().stop
|
||||||
|
@ -354,16 +365,30 @@ class Trip(models.Model):
|
||||||
def destination(self):
|
def destination(self):
|
||||||
return self.stop_times.order_by('-stop_sequence').first().stop
|
return self.stop_times.order_by('-stop_sequence').first().stop
|
||||||
|
|
||||||
|
@property
|
||||||
|
def departure_time(self):
|
||||||
|
dep_time = self.stop_times.order_by('stop_sequence').first().departure_time
|
||||||
|
hours = int(dep_time.total_seconds() // 3600)
|
||||||
|
minutes = int((dep_time.total_seconds() % 3600) // 60)
|
||||||
|
return f"{hours:02}:{minutes:02}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arrival_time(self):
|
||||||
|
arr_time = self.stop_times.order_by('-stop_sequence').first().arrival_time
|
||||||
|
hours = int(arr_time.total_seconds() // 3600)
|
||||||
|
minutes = int((arr_time.total_seconds() % 3600) // 60)
|
||||||
|
return f"{hours:02}:{minutes:02}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def train_type(self):
|
def train_type(self):
|
||||||
if self.service.transport_type == TransportType.TRANSILIEN:
|
if self.route.transport_type == TransportType.TRANSILIEN:
|
||||||
return self.route.short_name
|
return self.route.short_name
|
||||||
else:
|
else:
|
||||||
return self.origin.stop_type
|
return self.origin.stop_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def train_number(self):
|
def train_number(self):
|
||||||
if self.service.transport_type == TransportType.TRANSILIEN:
|
if self.route.transport_type == TransportType.TRANSILIEN:
|
||||||
return self.short_name
|
return self.short_name
|
||||||
else:
|
else:
|
||||||
return self.headsign
|
return self.headsign
|
||||||
|
@ -389,7 +414,8 @@ class Trip(models.Model):
|
||||||
return "000000"
|
return "000000"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.route.long_name} - {self.id}"
|
return f"{self.origin.name} {self.departure_time} → {self.destination.name} {self.arrival_time}" \
|
||||||
|
f" - {self.service_id}"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Trip")
|
verbose_name = _("Trip")
|
||||||
|
@ -470,7 +496,7 @@ class StopTime(models.Model):
|
||||||
return f"{hours:02}:{minutes:02}"
|
return f"{hours:02}:{minutes:02}"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.trip.route.long_name} - {self.trip_id} - {self.stop.name}"
|
return f"{self.stop.name} - {self.trip_id}"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Stop time")
|
verbose_name = _("Stop time")
|
||||||
|
@ -558,12 +584,6 @@ class CalendarDate(models.Model):
|
||||||
choices=ExceptionType,
|
choices=ExceptionType,
|
||||||
)
|
)
|
||||||
|
|
||||||
transport_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
verbose_name=_("Transport type"),
|
|
||||||
choices=TransportType,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.service.id} - {self.date} - {self.exception_type}"
|
return f"{self.service.id} - {self.date} - {self.exception_type}"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue