From 0486234b9fd0ba83960f839b3bb74844d35a0b03 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Fri, 10 May 2024 00:43:24 +0200 Subject: [PATCH] Import stations.csv file from Trainline --- trainvel/core/__init__.py | 0 trainvel/core/admin.py | 23 + trainvel/core/apps.py | 8 + trainvel/core/locale/fr/LC_MESSAGES/django.po | 325 ++++++++++ trainvel/core/management/__init__.py | 0 trainvel/core/management/commands/__init__.py | 0 .../commands/update_trainline_stations.py | 33 + trainvel/core/migrations/0001_initial.py | 603 ++++++++++++++++++ trainvel/core/migrations/__init__.py | 0 trainvel/core/models.py | 506 +++++++++++++++ trainvel/core/tests.py | 3 + trainvel/core/views.py | 3 + .../commands/update_trainvel_gtfs.py | 2 +- trainvel/settings.py | 1 + 14 files changed, 1506 insertions(+), 1 deletion(-) create mode 100644 trainvel/core/__init__.py create mode 100644 trainvel/core/admin.py create mode 100644 trainvel/core/apps.py create mode 100644 trainvel/core/locale/fr/LC_MESSAGES/django.po create mode 100644 trainvel/core/management/__init__.py create mode 100644 trainvel/core/management/commands/__init__.py create mode 100644 trainvel/core/management/commands/update_trainline_stations.py create mode 100644 trainvel/core/migrations/0001_initial.py create mode 100644 trainvel/core/migrations/__init__.py create mode 100644 trainvel/core/models.py create mode 100644 trainvel/core/tests.py create mode 100644 trainvel/core/views.py diff --git a/trainvel/core/__init__.py b/trainvel/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trainvel/core/admin.py b/trainvel/core/admin.py new file mode 100644 index 0000000..cc217fc --- /dev/null +++ b/trainvel/core/admin.py @@ -0,0 +1,23 @@ +from django.contrib import admin + +from trainvel.core.models import Station + + +class StationInline(admin.TabularInline): + model = Station + extra = 0 + autocomplete_fields = ('parent_station', 'same_as',) + show_change_link = True + ordering = ('name',) + readonly_fields = ('id',) + fk_name = 'parent_station' + + +@admin.register(Station) +class StationAdmin(admin.ModelAdmin): + list_display = ('name', 'country', 'uic', 'latitude', 'longitude',) + list_filter = ('country', 'is_city', 'is_main_station', 'is_airport', 'is_suggestable', + 'country_hint', 'main_station_hint',) + search_fields = ('name', 'slug',) + autocomplete_fields = ('parent_station', 'same_as',) + inlines = [StationInline] diff --git a/trainvel/core/apps.py b/trainvel/core/apps.py new file mode 100644 index 0000000..4279511 --- /dev/null +++ b/trainvel/core/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class CoreConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "trainvel.core" + verbose_name = _("Trainvel - Core") diff --git a/trainvel/core/locale/fr/LC_MESSAGES/django.po b/trainvel/core/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b645971 --- /dev/null +++ b/trainvel/core/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,325 @@ +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-09 22:04+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Emmy D'Anello \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: trainvel/core/apps.py:8 +msgid "Trainvel - Core" +msgstr "Trainvel - Cœur" + +#: trainvel/core/models.py:15 +msgid "name" +msgstr "nom" + +#: trainvel/core/models.py:20 +msgid "slug" +msgstr "slug" + +#: trainvel/core/models.py:24 +msgid "UIC" +msgstr "UIC" + +#: trainvel/core/models.py:31 +msgid "UIC8 SNCF" +msgstr "UIC8 SNCF" + +#: trainvel/core/models.py:38 +msgid "latitude" +msgstr "latitude" + +#: trainvel/core/models.py:45 +msgid "longitude" +msgstr "longitude" + +#: trainvel/core/models.py:54 +msgid "parent station" +msgstr "gare parente" + +#: trainvel/core/models.py:63 +msgid "country" +msgstr "pays" + +#: trainvel/core/models.py:69 +msgid "timezone" +msgstr "fuseau horaire" + +#: trainvel/core/models.py:73 +msgid "is city" +msgstr "est une ville" + +#: trainvel/core/models.py:77 +msgid "is main station" +msgstr "est une gare principale" + +#: trainvel/core/models.py:81 +msgid "is airport" +msgstr "est un aéroport" + +#: trainvel/core/models.py:85 +msgid "is suggestable" +msgstr "est suggérable" + +#: trainvel/core/models.py:89 +msgid "country hint" +msgstr "indice de pays" + +#: trainvel/core/models.py:93 +msgid "main station hint" +msgstr "indice de gare principale" + +#: trainvel/core/models.py:98 +msgid "SNCF ID" +msgstr "ID SNCF" + +#: trainvel/core/models.py:106 +msgid "SNCF TVS ID" +msgstr "ID SNCF TVS" + +#: trainvel/core/models.py:113 +msgid "SNCF is enabled" +msgstr "SNCF est activé" + +#: trainvel/core/models.py:118 +msgid "Entur ID" +msgstr "ID Entur" + +#: trainvel/core/models.py:125 +msgid "Entur is enabled" +msgstr "Entur est activé" + +#: trainvel/core/models.py:129 +msgid "DB ID" +msgstr "ID DB" + +#: trainvel/core/models.py:136 +msgid "DB is enabled" +msgstr "DB est activé" + +#: trainvel/core/models.py:141 +msgid "Busbud ID" +msgstr "ID Busbud" + +#: trainvel/core/models.py:148 +msgid "Busbud is enabled" +msgstr "Busbud est activé" + +#: trainvel/core/models.py:153 +msgid "distribusion ID" +msgstr "ID distribusion" + +#: trainvel/core/models.py:160 +msgid "distribusion is enabled" +msgstr "distribusion est activé" + +#: trainvel/core/models.py:164 +msgid "Flixbus ID" +msgstr "ID Flixbus" + +#: trainvel/core/models.py:171 +msgid "Flixbus is enabled" +msgstr "Flixbus est activé" + +#: trainvel/core/models.py:175 +msgid "CFF ID" +msgstr "ID CFF" + +#: trainvel/core/models.py:182 +msgid "CFF is enabled" +msgstr "CFF est activé" + +#: trainvel/core/models.py:187 +msgid "Leo Express ID" +msgstr "ID Leo Express" + +#: trainvel/core/models.py:194 +msgid "Leo Express is enabled" +msgstr "Leo Express est activé" + +#: trainvel/core/models.py:198 +msgid "ÖBB ID" +msgstr "ID ÖBB" + +#: trainvel/core/models.py:205 +msgid "ÖBB is enabled" +msgstr "ÖBB est activé" + +#: trainvel/core/models.py:210 +msgid "Ouigo ID" +msgstr "ID Ouigo" + +#: trainvel/core/models.py:217 +msgid "Ouigo is enabled" +msgstr "Ouigo est activé" + +#: trainvel/core/models.py:221 +msgid "Trenitalia ID" +msgstr "ID Trenitalia" + +#: trainvel/core/models.py:228 +msgid "Trenitalia is enabled" +msgstr "Trenitalia est activé" + +#: trainvel/core/models.py:233 +msgid "Trenitalia RTVT ID" +msgstr "ID Trenitalia RTVT" + +#: trainvel/core/models.py:241 +msgid "Trenord ID" +msgstr "ID Trenord" + +#: trainvel/core/models.py:249 +msgid "NTV RTIV ID" +msgstr "ID NTV RTIV" + +#: trainvel/core/models.py:257 +msgid "NTV ID" +msgstr "ID NTV" + +#: trainvel/core/models.py:264 +msgid "NTV is enabled" +msgstr "NTV est activé" + +#: trainvel/core/models.py:269 +msgid "HKX ID" +msgstr "ID HKX" + +#: trainvel/core/models.py:276 +msgid "HKX is enabled" +msgstr "HKX est activé" + +#: trainvel/core/models.py:280 +msgid "Renfe ID" +msgstr "ID Renfe" + +#: trainvel/core/models.py:287 +msgid "Renfe is enabled" +msgstr "Renfe est activé" + +#: trainvel/core/models.py:292 +msgid "ATOC ID" +msgstr "ID ATOC" + +#: trainvel/core/models.py:299 +msgid "ATOC is enabled" +msgstr "ATOC est activé" + +#: trainvel/core/models.py:304 +msgid "Benerail ID" +msgstr "ID Benerail" + +#: trainvel/core/models.py:311 +msgid "Benerail is enabled" +msgstr "Benerail est activé" + +#: trainvel/core/models.py:316 +msgid "Westbahn ID" +msgstr "ID Westbahn" + +#: trainvel/core/models.py:323 +msgid "Westbahn is enabled" +msgstr "Westbahn est activé" + +#: trainvel/core/models.py:327 +msgid "SNCF self-service machine" +msgstr "Automate self-service SNCF" + +#: trainvel/core/models.py:333 +msgid "same as" +msgstr "identique à" + +#: trainvel/core/models.py:342 +msgid "info (DE)" +msgstr "info (DE)" + +#: trainvel/core/models.py:350 +msgid "info (EN)" +msgstr "info (EN)" + +#: trainvel/core/models.py:358 +msgid "info (ES)" +msgstr "info (ES)" + +#: trainvel/core/models.py:366 +msgid "info (FR)" +msgstr "info (FR)" + +#: trainvel/core/models.py:374 +msgid "info (IT)" +msgstr "info (IT)" + +#: trainvel/core/models.py:382 +msgid "info (NB)" +msgstr "info (NB)" + +#: trainvel/core/models.py:390 +msgid "info (NL)" +msgstr "info (NL)" + +#: trainvel/core/models.py:398 +msgid "info (CS)" +msgstr "info (CS)" + +#: trainvel/core/models.py:406 +msgid "info (DA)" +msgstr "info (DA)" + +#: trainvel/core/models.py:414 +msgid "info (HU)" +msgstr "info (HU)" + +#: trainvel/core/models.py:422 +msgid "info (JA)" +msgstr "info (JA)" + +#: trainvel/core/models.py:430 +msgid "info (KO)" +msgstr "info (KO)" + +#: trainvel/core/models.py:438 +msgid "info (PL)" +msgstr "info (PL)" + +#: trainvel/core/models.py:446 +msgid "info (PT)" +msgstr "info (PT)" + +#: trainvel/core/models.py:454 +msgid "info (RU)" +msgstr "info (RU)" + +#: trainvel/core/models.py:462 +msgid "info (SV)" +msgstr "info (SV)" + +#: trainvel/core/models.py:470 +msgid "info (TR)" +msgstr "info (TR)" + +#: trainvel/core/models.py:478 +msgid "info (ZH)" +msgstr "info (ZH)" + +#: trainvel/core/models.py:486 +msgid "normalized code (Trainline)" +msgstr "code normalisé (Trainline)" + +#: trainvel/core/models.py:491 +msgid "IATA airport code" +msgstr "code aéroport IATA" + +#: trainvel/core/models.py:501 +msgid "station" +msgstr "gare" + +#: trainvel/core/models.py:502 +msgid "stations" +msgstr "gares" diff --git a/trainvel/core/management/__init__.py b/trainvel/core/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trainvel/core/management/commands/__init__.py b/trainvel/core/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trainvel/core/management/commands/update_trainline_stations.py b/trainvel/core/management/commands/update_trainline_stations.py new file mode 100644 index 0000000..11f1669 --- /dev/null +++ b/trainvel/core/management/commands/update_trainline_stations.py @@ -0,0 +1,33 @@ +import csv + +import requests +from django.core.management import BaseCommand +from tqdm import tqdm + +from trainvel.core.models import Station + + +class Command(BaseCommand): + def handle(self, *args, **options): + def convert_value(value: str) -> str: + return True if value == 't' else False if value == 'f' else (value or None) + + stations, stations_without_fk = [], [] + + STATIONS_URL = "https://raw.githubusercontent.com/trainline-eu/stations/master/stations.csv" + with requests.get(STATIONS_URL, stream=True) as resp: + for row in csv.DictReader(tqdm(resp.iter_lines(decode_unicode=True)), delimiter=';'): + row: dict + values = {k.replace(':', '_').replace('normalised_code', 'normalized_code_trainline') + .replace('same_as', 'same_as_id'): convert_value(v) + for k, v in row.items()} + values_without_fk = values.copy() + del values_without_fk['same_as_id'] + del values_without_fk['parent_station_id'] + stations.append(Station(**values)) + stations_without_fk.append(Station(**values_without_fk)) + + Station.objects.bulk_create(stations_without_fk, update_conflicts=True, unique_fields=['id'], + update_fields=[k for k in values_without_fk.keys() if k != 'id']) + Station.objects.bulk_create(stations, update_conflicts=True, unique_fields=['id'], + update_fields=['same_as_id', 'parent_station_id']) diff --git a/trainvel/core/migrations/0001_initial.py b/trainvel/core/migrations/0001_initial.py new file mode 100644 index 0000000..ef542ae --- /dev/null +++ b/trainvel/core/migrations/0001_initial.py @@ -0,0 +1,603 @@ +# Generated by Django 5.0.1 on 2024-05-09 22:15 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Station", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255, verbose_name="name")), + ("slug", models.SlugField(max_length=255, verbose_name="slug")), + ( + "uic", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="UIC" + ), + ), + ( + "uic8_sncf", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="UIC8 SNCF" + ), + ), + ( + "latitude", + models.FloatField( + blank=True, default=None, null=True, verbose_name="latitude" + ), + ), + ( + "longitude", + models.FloatField( + blank=True, default=None, null=True, verbose_name="longitude" + ), + ), + ( + "country", + models.CharField( + choices=[ + ("AL", "Albania"), + ("AD", "Andorra"), + ("AM", "Armenia"), + ("AT", "Austria"), + ("AZ", "Azerbaijan"), + ("BE", "Belgium"), + ("BA", "Bosnia and Herzegovina"), + ("BG", "Bulgaria"), + ("HR", "Croatia"), + ("CY", "Cyprus"), + ("CZ", "Czech Republic"), + ("DK", "Denmark"), + ("EE", "Estonia"), + ("FI", "Finland"), + ("FR", "France"), + ("GE", "Georgia"), + ("DE", "Germany"), + ("GR", "Greece"), + ("HU", "Hungary"), + ("IS", "Iceland"), + ("IE", "Ireland"), + ("IT", "Italy"), + ("LV", "Latvia"), + ("LI", "Liechtenstein"), + ("LT", "Lithuania"), + ("LU", "Luxembourg"), + ("MT", "Malta"), + ("MD", "Moldova"), + ("MC", "Monaco"), + ("ME", "Montenegro"), + ("NL", "Netherlands"), + ("MK", "North Macedonia"), + ("NO", "Norway"), + ("PL", "Poland"), + ("PT", "Portugal"), + ("RO", "Romania"), + ("SM", "San Marino"), + ("RS", "Serbia"), + ("SK", "Slovakia"), + ("SI", "Slovenia"), + ("ES", "Spain"), + ("SE", "Sweden"), + ("CH", "Switzerland"), + ("TR", "Turkey"), + ("GB", "United Kingdom"), + ("UA", "Ukraine"), + ], + max_length=255, + verbose_name="country", + ), + ), + ( + "time_zone", + models.CharField(max_length=255, verbose_name="timezone"), + ), + ("is_city", models.BooleanField(verbose_name="is city")), + ( + "is_main_station", + models.BooleanField(verbose_name="is main station"), + ), + ("is_airport", models.BooleanField(verbose_name="is airport")), + ("is_suggestable", models.BooleanField(verbose_name="is suggestable")), + ("country_hint", models.BooleanField(verbose_name="country hint")), + ( + "main_station_hint", + models.BooleanField(verbose_name="main station hint"), + ), + ( + "sncf_id", + models.CharField( + blank=True, + default=None, + max_length=5, + null=True, + verbose_name="SNCF ID", + ), + ), + ( + "sncf_tvs_id", + models.CharField( + blank=True, + default=None, + max_length=3, + null=True, + verbose_name="SNCF TVS ID", + ), + ), + ( + "sncf_is_enabled", + models.BooleanField(verbose_name="SNCF is enabled"), + ), + ( + "entur_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Entur ID", + ), + ), + ( + "entur_is_enabled", + models.BooleanField(verbose_name="Entur is enabled"), + ), + ( + "db_id", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="DB ID" + ), + ), + ("db_is_enabled", models.BooleanField(verbose_name="DB is enabled")), + ( + "busbud_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Busbud ID", + ), + ), + ( + "busbud_is_enabled", + models.BooleanField(verbose_name="Busbud is enabled"), + ), + ( + "distribusion_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="distribusion ID", + ), + ), + ( + "distribusion_is_enabled", + models.BooleanField(verbose_name="distribusion is enabled"), + ), + ( + "flixbus_id", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="Flixbus ID" + ), + ), + ( + "flixbus_is_enabled", + models.BooleanField(verbose_name="Flixbus is enabled"), + ), + ( + "cff_id", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="CFF ID" + ), + ), + ("cff_is_enabled", models.BooleanField(verbose_name="CFF is enabled")), + ( + "leoexpress_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Leo Express ID", + ), + ), + ( + "leoexpress_is_enabled", + models.BooleanField(verbose_name="Leo Express is enabled"), + ), + ( + "obb_id", + models.IntegerField( + blank=True, default=None, null=True, verbose_name="ÖBB ID" + ), + ), + ("obb_is_enabled", models.BooleanField(verbose_name="ÖBB is enabled")), + ( + "ouigo_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Ouigo ID", + ), + ), + ( + "ouigo_is_enabled", + models.BooleanField(verbose_name="Ouigo is enabled"), + ), + ( + "trenitalia_id", + models.IntegerField( + blank=True, + default=None, + null=True, + verbose_name="Trenitalia ID", + ), + ), + ( + "trenitalia_is_enabled", + models.BooleanField(verbose_name="Trenitalia is enabled"), + ), + ( + "trenitalia_rtvt_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Trenitalia RTVT ID", + ), + ), + ( + "trenord_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Trenord ID", + ), + ), + ( + "ntv_rtiv_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="NTV RTIV ID", + ), + ), + ( + "ntv_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="NTV ID", + ), + ), + ("ntv_is_enabled", models.BooleanField(verbose_name="NTV is enabled")), + ( + "hkx_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="HKX ID", + ), + ), + ("hkx_is_enabled", models.BooleanField(verbose_name="HKX is enabled")), + ( + "renfe_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Renfe ID", + ), + ), + ( + "renfe_is_enabled", + models.BooleanField(verbose_name="Renfe is enabled"), + ), + ( + "atoc_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="ATOC ID", + ), + ), + ( + "atoc_is_enabled", + models.BooleanField(verbose_name="ATOC is enabled"), + ), + ( + "benerail_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Benerail ID", + ), + ), + ( + "benerail_is_enabled", + models.BooleanField(verbose_name="Benerail is enabled"), + ), + ( + "westbahn_id", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="Westbahn ID", + ), + ), + ( + "westbahn_is_enabled", + models.BooleanField(verbose_name="Westbahn is enabled"), + ), + ( + "sncf_self_service_machine", + models.BooleanField(verbose_name="SNCF self-service machine"), + ), + ( + "info_de", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (DE)", + ), + ), + ( + "info_en", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (EN)", + ), + ), + ( + "info_es", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (ES)", + ), + ), + ( + "info_fr", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (FR)", + ), + ), + ( + "info_it", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (IT)", + ), + ), + ( + "info_nb", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (NB)", + ), + ), + ( + "info_nl", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (NL)", + ), + ), + ( + "info_cs", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (CS)", + ), + ), + ( + "info_da", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (DA)", + ), + ), + ( + "info_hu", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (HU)", + ), + ), + ( + "info_ja", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (JA)", + ), + ), + ( + "info_ko", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (KO)", + ), + ), + ( + "info_pl", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (PL)", + ), + ), + ( + "info_pt", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (PT)", + ), + ), + ( + "info_ru", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (RU)", + ), + ), + ( + "info_sv", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (SV)", + ), + ), + ( + "info_tr", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (TR)", + ), + ), + ( + "info_zh", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="info (ZH)", + ), + ), + ( + "normalized_code_trainline", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="normalized code (Trainline)", + ), + ), + ( + "iata_airport_code", + models.CharField( + blank=True, + default=None, + max_length=255, + null=True, + verbose_name="IATA airport code", + ), + ), + ( + "parent_station", + models.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="core.station", + verbose_name="parent station", + ), + ), + ( + "same_as", + models.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="same_as_other", + to="core.station", + verbose_name="same as", + ), + ), + ], + options={ + "verbose_name": "station", + "verbose_name_plural": "stations", + }, + ), + ] diff --git a/trainvel/core/migrations/__init__.py b/trainvel/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trainvel/core/models.py b/trainvel/core/models.py new file mode 100644 index 0000000..42347cb --- /dev/null +++ b/trainvel/core/models.py @@ -0,0 +1,506 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from trainvel.gtfs.models import Country + + +class Station(models.Model): + """ + Describes the content of the stations CSV file generated by Trainline. + The CSV file can be found at https://raw.githubusercontent.com/trainline-eu/stations/master/stations.csv + """ + + name = models.CharField( + max_length=255, + verbose_name=_("name"), + ) + + slug = models.SlugField( + max_length=255, + verbose_name=_("slug"), + ) + + uic = models.IntegerField( + verbose_name=_("UIC"), + blank=True, + null=True, + default=None, + ) + + uic8_sncf = models.IntegerField( + verbose_name=_("UIC8 SNCF"), + blank=True, + null=True, + default=None, + ) + + latitude = models.FloatField( + verbose_name=_("latitude"), + blank=True, + null=True, + default=None, + ) + + longitude = models.FloatField( + verbose_name=_("longitude"), + blank=True, + null=True, + default=None, + ) + + parent_station = models.ForeignKey( + "Station", + on_delete=models.CASCADE, + verbose_name=_("parent station"), + blank=True, + null=True, + default=None, + related_name="children", + ) + + country = models.CharField( + max_length=255, + verbose_name=_("country"), + choices=Country, + ) + + time_zone = models.CharField( + max_length=255, + verbose_name=_("timezone"), + ) + + is_city = models.BooleanField( + verbose_name=_("is city"), + ) + + is_main_station = models.BooleanField( + verbose_name=_("is main station"), + ) + + is_airport = models.BooleanField( + verbose_name=_("is airport"), + ) + + is_suggestable = models.BooleanField( + verbose_name=_("is suggestable"), + ) + + country_hint = models.BooleanField( + verbose_name=_("country hint"), + ) + + main_station_hint = models.BooleanField( + verbose_name=_("main station hint"), + ) + + sncf_id = models.CharField( + max_length=5, + verbose_name=_("SNCF ID"), + blank=True, + null=True, + default=None, + ) + + sncf_tvs_id = models.CharField( + max_length=3, + verbose_name=_("SNCF TVS ID"), + blank=True, + null=True, + default=None, + ) + + sncf_is_enabled = models.BooleanField( + verbose_name=_("SNCF is enabled"), + ) + + entur_id = models.CharField( + max_length=255, + verbose_name=_("Entur ID"), + blank=True, + null=True, + default=None, + ) + + entur_is_enabled = models.BooleanField( + verbose_name=_("Entur is enabled"), + ) + + db_id = models.IntegerField( + verbose_name=_("DB ID"), + blank=True, + null=True, + default=None, + ) + + db_is_enabled = models.BooleanField( + verbose_name=_("DB is enabled"), + ) + + busbud_id = models.CharField( + max_length=255, + verbose_name=_("Busbud ID"), + blank=True, + null=True, + default=None, + ) + + busbud_is_enabled = models.BooleanField( + verbose_name=_("Busbud is enabled"), + ) + + distribusion_id = models.CharField( + max_length=255, + verbose_name=_("distribusion ID"), + blank=True, + null=True, + default=None, + ) + + distribusion_is_enabled = models.BooleanField( + verbose_name=_("distribusion is enabled"), + ) + + flixbus_id = models.IntegerField( + verbose_name=_("Flixbus ID"), + blank=True, + null=True, + default=None, + ) + + flixbus_is_enabled = models.BooleanField( + verbose_name=_("Flixbus is enabled"), + ) + + cff_id = models.IntegerField( + verbose_name=_("CFF ID"), + blank=True, + null=True, + default=None, + ) + + cff_is_enabled = models.BooleanField( + verbose_name=_("CFF is enabled"), + ) + + leoexpress_id = models.CharField( + max_length=255, + verbose_name=_("Leo Express ID"), + blank=True, + null=True, + default=None, + ) + + leoexpress_is_enabled = models.BooleanField( + verbose_name=_("Leo Express is enabled"), + ) + + obb_id = models.IntegerField( + verbose_name=_("ÖBB ID"), + blank=True, + null=True, + default=None, + ) + + obb_is_enabled = models.BooleanField( + verbose_name=_("ÖBB is enabled"), + ) + + ouigo_id = models.CharField( + max_length=255, + verbose_name=_("Ouigo ID"), + blank=True, + null=True, + default=None, + ) + + ouigo_is_enabled = models.BooleanField( + verbose_name=_("Ouigo is enabled"), + ) + + trenitalia_id = models.IntegerField( + verbose_name=_("Trenitalia ID"), + blank=True, + null=True, + default=None, + ) + + trenitalia_is_enabled = models.BooleanField( + verbose_name=_("Trenitalia is enabled"), + ) + + trenitalia_rtvt_id = models.CharField( + max_length=255, + verbose_name=_("Trenitalia RTVT ID"), + blank=True, + null=True, + default=None, + ) + + trenord_id = models.CharField( + max_length=255, + verbose_name=_("Trenord ID"), + blank=True, + null=True, + default=None, + ) + + ntv_rtiv_id = models.CharField( + max_length=255, + verbose_name=_("NTV RTIV ID"), + blank=True, + null=True, + default=None, + ) + + ntv_id = models.CharField( + max_length=255, + verbose_name=_("NTV ID"), + blank=True, + null=True, + default=None, + ) + + ntv_is_enabled = models.BooleanField( + verbose_name=_("NTV is enabled"), + ) + + hkx_id = models.CharField( + max_length=255, + verbose_name=_("HKX ID"), + blank=True, + null=True, + default=None, + ) + + hkx_is_enabled = models.BooleanField( + verbose_name=_("HKX is enabled"), + ) + + renfe_id = models.CharField( + max_length=255, + verbose_name=_("Renfe ID"), + blank=True, + null=True, + default=None, + ) + + renfe_is_enabled = models.BooleanField( + verbose_name=_("Renfe is enabled"), + ) + + atoc_id = models.CharField( + max_length=255, + verbose_name=_("ATOC ID"), + blank=True, + null=True, + default=None, + ) + + atoc_is_enabled = models.BooleanField( + verbose_name=_("ATOC is enabled"), + ) + + benerail_id = models.CharField( + max_length=255, + verbose_name=_("Benerail ID"), + blank=True, + null=True, + default=None, + ) + + benerail_is_enabled = models.BooleanField( + verbose_name=_("Benerail is enabled"), + ) + + westbahn_id = models.CharField( + max_length=255, + verbose_name=_("Westbahn ID"), + blank=True, + null=True, + default=None, + ) + + westbahn_is_enabled = models.BooleanField( + verbose_name=_("Westbahn is enabled"), + ) + + sncf_self_service_machine = models.BooleanField( + verbose_name=_("SNCF self-service machine"), + ) + + same_as = models.ForeignKey( + "Station", + on_delete=models.CASCADE, + verbose_name=_("same as"), + blank=True, + null=True, + default=None, + related_name="same_as_other", + ) + + info_de = models.CharField( + max_length=255, + verbose_name=_("info (DE)"), + blank=True, + null=True, + default=None, + ) + + info_en = models.CharField( + max_length=255, + verbose_name=_("info (EN)"), + blank=True, + null=True, + default=None, + ) + + info_es = models.CharField( + max_length=255, + verbose_name=_("info (ES)"), + blank=True, + null=True, + default=None, + ) + + info_fr = models.CharField( + max_length=255, + verbose_name=_("info (FR)"), + blank=True, + null=True, + default=None, + ) + + info_it = models.CharField( + max_length=255, + verbose_name=_("info (IT)"), + blank=True, + null=True, + default=None, + ) + + info_nb = models.CharField( + max_length=255, + verbose_name=_("info (NB)"), + blank=True, + null=True, + default=None, + ) + + info_nl = models.CharField( + max_length=255, + verbose_name=_("info (NL)"), + blank=True, + null=True, + default=None, + ) + + info_cs = models.CharField( + max_length=255, + verbose_name=_("info (CS)"), + blank=True, + null=True, + default=None, + ) + + info_da = models.CharField( + max_length=255, + verbose_name=_("info (DA)"), + blank=True, + null=True, + default=None, + ) + + info_hu = models.CharField( + max_length=255, + verbose_name=_("info (HU)"), + blank=True, + null=True, + default=None, + ) + + info_ja = models.CharField( + max_length=255, + verbose_name=_("info (JA)"), + blank=True, + null=True, + default=None, + ) + + info_ko = models.CharField( + max_length=255, + verbose_name=_("info (KO)"), + blank=True, + null=True, + default=None, + ) + + info_pl = models.CharField( + max_length=255, + verbose_name=_("info (PL)"), + blank=True, + null=True, + default=None, + ) + + info_pt = models.CharField( + max_length=255, + verbose_name=_("info (PT)"), + blank=True, + null=True, + default=None, + ) + + info_ru = models.CharField( + max_length=255, + verbose_name=_("info (RU)"), + blank=True, + null=True, + default=None, + ) + + info_sv = models.CharField( + max_length=255, + verbose_name=_("info (SV)"), + blank=True, + null=True, + default=None, + ) + + info_tr = models.CharField( + max_length=255, + verbose_name=_("info (TR)"), + blank=True, + null=True, + default=None, + ) + + info_zh = models.CharField( + max_length=255, + verbose_name=_("info (ZH)"), + blank=True, + null=True, + default=None, + ) + + normalized_code_trainline = models.CharField( + max_length=255, + verbose_name=_("normalized code (Trainline)"), + blank=True, + null=True, + default=None, + ) + + iata_airport_code = models.CharField( + max_length=255, + verbose_name=_("IATA airport code"), + blank=True, + null=True, + default=None, + ) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _("station") + verbose_name_plural = _("stations") diff --git a/trainvel/core/tests.py b/trainvel/core/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/trainvel/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/trainvel/core/views.py b/trainvel/core/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/trainvel/core/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/trainvel/gtfs/management/commands/update_trainvel_gtfs.py b/trainvel/gtfs/management/commands/update_trainvel_gtfs.py index 3633f8a..5af1bf8 100644 --- a/trainvel/gtfs/management/commands/update_trainvel_gtfs.py +++ b/trainvel/gtfs/management/commands/update_trainvel_gtfs.py @@ -155,7 +155,7 @@ class Command(BaseCommand): unique_fields=['id']) routes.clear() - # Calendar.objects.filter(gtfs_feed=gtfs_feed).delete() + Calendar.objects.filter(gtfs_feed=gtfs_feed).delete() calendars = {} if "calendar.txt" in zipfile.namelist(): for calendar_dict in csv.DictReader(tqdm(read_file("calendar.txt"), desc="Calendars")): diff --git a/trainvel/settings.py b/trainvel/settings.py index 7e085b0..e652440 100644 --- a/trainvel/settings.py +++ b/trainvel/settings.py @@ -45,6 +45,7 @@ INSTALLED_APPS = [ "rest_framework", "trainvel.api", + "trainvel.core", "trainvel.gtfs", ]