From 44b93bd5e864109067d1a4a27a3a663de94e87f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 11:05:34 +0200 Subject: [PATCH 1/9] Minor admin improvements --- dcc/metadata/admin.py | 4 ++++ .../0002_alter_rollingstock_address.py | 18 ++++++++++++++++++ dcc/roster/models.py | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 dcc/roster/migrations/0002_alter_rollingstock_address.py diff --git a/dcc/metadata/admin.py b/dcc/metadata/admin.py index 98bd15f..1c3f400 100644 --- a/dcc/metadata/admin.py +++ b/dcc/metadata/admin.py @@ -6,11 +6,15 @@ from metadata.models import ( @admin.register(Decoder) class DecoderAdmin(admin.ModelAdmin): readonly_fields = ('image_thumbnail',) + list_display = ('__str__', 'interface') + list_filter = ('manufacturer', 'interface') @admin.register(Company) class CompanyAdmin(admin.ModelAdmin): readonly_fields = ('logo_thumbnail',) + list_display = ('name', 'country') + list_filter = list_display @admin.register(Manufacturer) diff --git a/dcc/roster/migrations/0002_alter_rollingstock_address.py b/dcc/roster/migrations/0002_alter_rollingstock_address.py new file mode 100644 index 0000000..6d4d23d --- /dev/null +++ b/dcc/roster/migrations/0002_alter_rollingstock_address.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.2 on 2022-04-01 20:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='rollingstock', + name='address', + field=models.SmallIntegerField(blank=True, default=None, null=True), + ), + ] diff --git a/dcc/roster/models.py b/dcc/roster/models.py index e641df8..5a07d44 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -23,7 +23,7 @@ class RollingStock(models.Model): Tag, related_name='rolling_stock', blank=True) - address = models.SmallIntegerField(default=3, null=True, blank=True) + address = models.SmallIntegerField(default=None, null=True, blank=True) manufacturer = models.ForeignKey( Manufacturer, on_delete=models.CASCADE, null=True, blank=True) From 915bc13575440c1884daf106e1bf317c31a8d13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 12:43:40 +0200 Subject: [PATCH 2/9] Add consist app --- dcc/consist/__init__.py | 0 dcc/consist/admin.py | 35 ++++++++++++ dcc/consist/apps.py | 6 +++ dcc/consist/migrations/0001_initial.py | 39 ++++++++++++++ ...r_consistitem_options_consistitem_order.py | 22 ++++++++ .../migrations/0003_consist_address.py | 18 +++++++ dcc/consist/migrations/__init__.py | 0 dcc/consist/models.py | 53 +++++++++++++++++++ dcc/consist/tests.py | 3 ++ dcc/consist/views.py | 3 ++ dcc/dcc/settings.py | 2 + dcc/roster/admin.py | 2 +- .../migrations/0003_consistitem_consist.py | 36 +++++++++++++ .../migrations/0004_consistitem_consist.py | 20 +++++++ ...005_remove_consistitem_consist_and_more.py | 27 ++++++++++ dcc/roster/models.py | 2 - requirements.txt | 1 + 17 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 dcc/consist/__init__.py create mode 100644 dcc/consist/admin.py create mode 100644 dcc/consist/apps.py create mode 100644 dcc/consist/migrations/0001_initial.py create mode 100644 dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py create mode 100644 dcc/consist/migrations/0003_consist_address.py create mode 100644 dcc/consist/migrations/__init__.py create mode 100644 dcc/consist/models.py create mode 100644 dcc/consist/tests.py create mode 100644 dcc/consist/views.py create mode 100644 dcc/roster/migrations/0003_consistitem_consist.py create mode 100644 dcc/roster/migrations/0004_consistitem_consist.py create mode 100644 dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py diff --git a/dcc/consist/__init__.py b/dcc/consist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dcc/consist/admin.py b/dcc/consist/admin.py new file mode 100644 index 0000000..f21151d --- /dev/null +++ b/dcc/consist/admin.py @@ -0,0 +1,35 @@ +from django.contrib import admin +from adminsortable2.admin import SortableInlineAdminMixin + +from consist.models import Consist, ConsistItem + + +class ConsistItemInline(SortableInlineAdminMixin, admin.TabularInline): + model = ConsistItem + min_num = 1 + extra = 0 + readonly_fields = ('address', 'company', 'epoch') + + +@admin.register(Consist) +class ConsistAdmin(admin.ModelAdmin): + inlines = (ConsistItemInline,) + readonly_fields = ('creation_time', 'updated_time',) + list_display = ('identifier', 'company', 'epoch') + list_filter = list_display + search_fields = list_display + + fieldsets = ( + (None, { + 'fields': ('identifier', + 'address', + 'tags', + 'company', + 'epoch', + 'notes') + }), + ('Audit', { + 'classes': ('collapse',), + 'fields': ('creation_time', 'updated_time',) + }), + ) diff --git a/dcc/consist/apps.py b/dcc/consist/apps.py new file mode 100644 index 0000000..5f3aa65 --- /dev/null +++ b/dcc/consist/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ConsistConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'consist' diff --git a/dcc/consist/migrations/0001_initial.py b/dcc/consist/migrations/0001_initial.py new file mode 100644 index 0000000..5501547 --- /dev/null +++ b/dcc/consist/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 4.0.2 on 2022-04-02 09:22 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('metadata', '0001_initial'), + ('roster', '0005_remove_consistitem_consist_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Consist', + fields=[ + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('identifier', models.CharField(max_length=128)), + ('epoch', models.CharField(blank=True, max_length=32)), + ('notes', models.TextField(blank=True)), + ('creation_time', models.DateTimeField(auto_now_add=True)), + ('updated_time', models.DateTimeField(auto_now=True)), + ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.company')), + ('tags', models.ManyToManyField(blank=True, related_name='consist', to='metadata.Tag')), + ], + ), + migrations.CreateModel( + name='ConsistItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('consist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='consist.consist')), + ('rolling_stock', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='roster.rollingstock')), + ], + ), + ] diff --git a/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py b/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py new file mode 100644 index 0000000..3f60510 --- /dev/null +++ b/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py @@ -0,0 +1,22 @@ +# Generated by Django 4.0.2 on 2022-04-02 09:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consist', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='consistitem', + options={'ordering': ['order']}, + ), + migrations.AddField( + model_name='consistitem', + name='order', + field=models.PositiveIntegerField(default=0), + ), + ] diff --git a/dcc/consist/migrations/0003_consist_address.py b/dcc/consist/migrations/0003_consist_address.py new file mode 100644 index 0000000..cabd1e8 --- /dev/null +++ b/dcc/consist/migrations/0003_consist_address.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.2 on 2022-04-02 10:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consist', '0002_alter_consistitem_options_consistitem_order'), + ] + + operations = [ + migrations.AddField( + model_name='consist', + name='address', + field=models.SmallIntegerField(blank=True, default=None, null=True), + ), + ] diff --git a/dcc/consist/migrations/__init__.py b/dcc/consist/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dcc/consist/models.py b/dcc/consist/models.py new file mode 100644 index 0000000..d45fb9a --- /dev/null +++ b/dcc/consist/models.py @@ -0,0 +1,53 @@ +from uuid import uuid4 +from django.db import models + +from metadata.models import Company, Tag +from roster.models import RollingStock + + +class Consist(models.Model): + uuid = models.UUIDField( + primary_key=True, default=uuid4, + editable=False) + identifier = models.CharField(max_length=128, unique=False) + tags = models.ManyToManyField( + Tag, + related_name='consist', + blank=True) + address = models.SmallIntegerField(default=None, null=True, blank=True) + company = models.ForeignKey( + Company, on_delete=models.CASCADE, + null=True, blank=True) + epoch = models.CharField(max_length=32, blank=True) + notes = models.TextField(blank=True) + creation_time = models.DateTimeField(auto_now_add=True) + updated_time = models.DateTimeField(auto_now=True) + + def __str__(self): + return "{0}".format(self.identifier) + + +class ConsistItem(models.Model): + consist = models.ForeignKey( + Consist, on_delete=models.CASCADE) + rolling_stock = models.ForeignKey( + RollingStock, on_delete=models.CASCADE) + order = models.PositiveIntegerField(default=0, blank=False, null=False) + + class Meta(object): + ordering = ['order'] + + def __str__(self): + return "{0}".format(self.rolling_stock.identifier) + + # def type(self): + # return self.rolling_stock.type + + def address(self): + return self.rolling_stock.address + + def company(self): + return self.rolling_stock.company + + def epoch(self): + return self.rolling_stock.epoch diff --git a/dcc/consist/tests.py b/dcc/consist/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/dcc/consist/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/dcc/consist/views.py b/dcc/consist/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/dcc/consist/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/dcc/dcc/settings.py b/dcc/dcc/settings.py index 6eaa721..bb9408c 100644 --- a/dcc/dcc/settings.py +++ b/dcc/dcc/settings.py @@ -43,10 +43,12 @@ INSTALLED_APPS = [ 'django_countries', 'solo', 'rest_framework', + 'adminsortable2', 'dcc', 'driver', 'metadata', 'roster', + 'consist', ] MIDDLEWARE = [ diff --git a/dcc/roster/admin.py b/dcc/roster/admin.py index 40766c4..cada57d 100644 --- a/dcc/roster/admin.py +++ b/dcc/roster/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from roster.models import ( - RollingStock, RollingStockImage, RollingStockDocument, Engine, Car, + RollingStockImage, RollingStockDocument, Engine, Car, Equipment, Other) diff --git a/dcc/roster/migrations/0003_consistitem_consist.py b/dcc/roster/migrations/0003_consistitem_consist.py new file mode 100644 index 0000000..6017596 --- /dev/null +++ b/dcc/roster/migrations/0003_consistitem_consist.py @@ -0,0 +1,36 @@ +# Generated by Django 4.0.2 on 2022-04-02 09:09 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0001_initial'), + ('roster', '0002_alter_rollingstock_address'), + ] + + operations = [ + migrations.CreateModel( + name='ConsistItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('rolling_stock', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='roster.rollingstock')), + ], + ), + migrations.CreateModel( + name='Consist', + fields=[ + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('identifier', models.CharField(max_length=128)), + ('epoch', models.CharField(blank=True, max_length=32)), + ('notes', models.TextField(blank=True)), + ('creation_time', models.DateTimeField(auto_now_add=True)), + ('updated_time', models.DateTimeField(auto_now=True)), + ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.company')), + ('tags', models.ManyToManyField(blank=True, related_name='consist', to='metadata.Tag')), + ], + ), + ] diff --git a/dcc/roster/migrations/0004_consistitem_consist.py b/dcc/roster/migrations/0004_consistitem_consist.py new file mode 100644 index 0000000..2cf1d18 --- /dev/null +++ b/dcc/roster/migrations/0004_consistitem_consist.py @@ -0,0 +1,20 @@ +# Generated by Django 4.0.2 on 2022-04-02 09:13 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0003_consistitem_consist'), + ] + + operations = [ + migrations.AddField( + model_name='consistitem', + name='consist', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='roster.consist'), + preserve_default=False, + ), + ] diff --git a/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py b/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py new file mode 100644 index 0000000..d4be8cc --- /dev/null +++ b/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.0.2 on 2022-04-02 09:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0004_consistitem_consist'), + ] + + operations = [ + migrations.RemoveField( + model_name='consistitem', + name='consist', + ), + migrations.RemoveField( + model_name='consistitem', + name='rolling_stock', + ), + migrations.DeleteModel( + name='Consist', + ), + migrations.DeleteModel( + name='ConsistItem', + ), + ] diff --git a/dcc/roster/models.py b/dcc/roster/models.py index 5a07d44..fd062f1 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -37,9 +37,7 @@ class RollingStock(models.Model): epoch = models.CharField(max_length=32, blank=True) production_year = models.SmallIntegerField(null=True, blank=True) purchase_date = models.DateField(null=True, blank=True) - notes = models.TextField(blank=True) - creation_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True) diff --git a/requirements.txt b/requirements.txt index 3c71f53..bf774ee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,7 @@ djangorestframework django-solo django-countries django-health-check +django-admin-sortable2 # psycopg2-binary # paho-mqtt # asyncio-mqtt From fd43ee34cba80e672b4e7c0947a85e5dcb588799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 18:33:29 +0200 Subject: [PATCH 3/9] Refactor roster and initial support for consists --- dcc/consist/admin.py | 12 +-- dcc/consist/migrations/0001_initial.py | 9 +- ...r_consistitem_options_consistitem_order.py | 22 ----- ...ddress_consist_consist_address_and_more.py | 23 +++++ .../migrations/0003_consist_address.py | 18 ---- dcc/consist/models.py | 17 ++-- dcc/dcc/settings.py | 20 ++++- dcc/dcc/urls.py | 4 +- dcc/metadata/admin.py | 8 +- dcc/metadata/migrations/0001_initial.py | 5 +- ...002_scale_manufacturer_website_and_more.py | 32 +++++++ dcc/metadata/models.py | 22 +++-- dcc/roster/admin.py | 50 ++++------- dcc/roster/migrations/0001_initial.py | 50 +++-------- .../0002_alter_rollingstock_address.py | 18 ---- ...ass_alter_rollingclass_options_and_more.py | 48 ++++++++++ .../migrations/0003_consistitem_consist.py | 36 -------- .../migrations/0004_consistitem_consist.py | 20 ----- ...005_remove_consistitem_consist_and_more.py | 27 ------ dcc/roster/models.py | 90 +++++++++---------- 20 files changed, 245 insertions(+), 286 deletions(-) delete mode 100644 dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py create mode 100644 dcc/consist/migrations/0002_rename_address_consist_consist_address_and_more.py delete mode 100644 dcc/consist/migrations/0003_consist_address.py create mode 100644 dcc/metadata/migrations/0002_scale_manufacturer_website_and_more.py delete mode 100644 dcc/roster/migrations/0002_alter_rollingstock_address.py create mode 100644 dcc/roster/migrations/0002_rename_class_rollingclass_alter_rollingclass_options_and_more.py delete mode 100644 dcc/roster/migrations/0003_consistitem_consist.py delete mode 100644 dcc/roster/migrations/0004_consistitem_consist.py delete mode 100644 dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py diff --git a/dcc/consist/admin.py b/dcc/consist/admin.py index f21151d..ffa3a48 100644 --- a/dcc/consist/admin.py +++ b/dcc/consist/admin.py @@ -8,25 +8,25 @@ class ConsistItemInline(SortableInlineAdminMixin, admin.TabularInline): model = ConsistItem min_num = 1 extra = 0 - readonly_fields = ('address', 'company', 'epoch') + readonly_fields = ('address', 'type', 'company', 'era') @admin.register(Consist) class ConsistAdmin(admin.ModelAdmin): inlines = (ConsistItemInline,) readonly_fields = ('creation_time', 'updated_time',) - list_display = ('identifier', 'company', 'epoch') + list_display = ('identifier', 'company', 'era') list_filter = list_display search_fields = list_display fieldsets = ( (None, { 'fields': ('identifier', - 'address', - 'tags', + 'consist_address', 'company', - 'epoch', - 'notes') + 'era', + 'notes', + 'tags') }), ('Audit', { 'classes': ('collapse',), diff --git a/dcc/consist/migrations/0001_initial.py b/dcc/consist/migrations/0001_initial.py index 5501547..df46d20 100644 --- a/dcc/consist/migrations/0001_initial.py +++ b/dcc/consist/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.0.2 on 2022-04-02 09:22 +# Generated by Django 4.0.2 on 2022-04-02 14:25 from django.db import migrations, models import django.db.models.deletion @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('roster', '0001_initial'), ('metadata', '0001_initial'), - ('roster', '0005_remove_consistitem_consist_and_more'), ] operations = [ @@ -20,6 +20,7 @@ class Migration(migrations.Migration): fields=[ ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('identifier', models.CharField(max_length=128)), + ('address', models.SmallIntegerField(blank=True, default=None, null=True)), ('epoch', models.CharField(blank=True, max_length=32)), ('notes', models.TextField(blank=True)), ('creation_time', models.DateTimeField(auto_now_add=True)), @@ -32,8 +33,12 @@ class Migration(migrations.Migration): name='ConsistItem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.PositiveIntegerField(default=0)), ('consist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='consist.consist')), ('rolling_stock', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='roster.rollingstock')), ], + options={ + 'ordering': ['order'], + }, ), ] diff --git a/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py b/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py deleted file mode 100644 index 3f60510..0000000 --- a/dcc/consist/migrations/0002_alter_consistitem_options_consistitem_order.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-02 09:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('consist', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='consistitem', - options={'ordering': ['order']}, - ), - migrations.AddField( - model_name='consistitem', - name='order', - field=models.PositiveIntegerField(default=0), - ), - ] diff --git a/dcc/consist/migrations/0002_rename_address_consist_consist_address_and_more.py b/dcc/consist/migrations/0002_rename_address_consist_consist_address_and_more.py new file mode 100644 index 0000000..db729ca --- /dev/null +++ b/dcc/consist/migrations/0002_rename_address_consist_consist_address_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.2 on 2022-04-02 16:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('consist', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='consist', + old_name='address', + new_name='consist_address', + ), + migrations.RenameField( + model_name='consist', + old_name='epoch', + new_name='era', + ), + ] diff --git a/dcc/consist/migrations/0003_consist_address.py b/dcc/consist/migrations/0003_consist_address.py deleted file mode 100644 index cabd1e8..0000000 --- a/dcc/consist/migrations/0003_consist_address.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-02 10:36 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('consist', '0002_alter_consistitem_options_consistitem_order'), - ] - - operations = [ - migrations.AddField( - model_name='consist', - name='address', - field=models.SmallIntegerField(blank=True, default=None, null=True), - ), - ] diff --git a/dcc/consist/models.py b/dcc/consist/models.py index d45fb9a..16f4fc5 100644 --- a/dcc/consist/models.py +++ b/dcc/consist/models.py @@ -14,11 +14,12 @@ class Consist(models.Model): Tag, related_name='consist', blank=True) - address = models.SmallIntegerField(default=None, null=True, blank=True) + consist_address = models.SmallIntegerField( + default=None, null=True, blank=True) company = models.ForeignKey( Company, on_delete=models.CASCADE, null=True, blank=True) - epoch = models.CharField(max_length=32, blank=True) + era = models.CharField(max_length=32, blank=True) notes = models.TextField(blank=True) creation_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True) @@ -38,16 +39,16 @@ class ConsistItem(models.Model): ordering = ['order'] def __str__(self): - return "{0}".format(self.rolling_stock.identifier) + return "{0}".format(self.rolling_stock) - # def type(self): - # return self.rolling_stock.type + def type(self): + return self.rolling_stock.rolling_class.type def address(self): return self.rolling_stock.address def company(self): - return self.rolling_stock.company + return self.rolling_stock.company() - def epoch(self): - return self.rolling_stock.epoch + def era(self): + return self.rolling_stock.era diff --git a/dcc/dcc/settings.py b/dcc/dcc/settings.py index bb9408c..3475115 100644 --- a/dcc/dcc/settings.py +++ b/dcc/dcc/settings.py @@ -137,7 +137,21 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' MEDIA_URL = 'media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') -ROLLING_STOCK_TYPES = [ - ("engine", "Engine"), ("car", "Car"), - ("equipment", "Equipment"), ("other", "Other") +COUNTRIES_OVERRIDE = { + 'ZZ': "Freelance", +} + +DECODER_INTERFACES = [ + (1, "NEM651"), + (2, "NEM652"), + (3, "PluX"), + (4, "21MTC"), + (5, "Next18/Next18S") +] + +ROLLING_STOCK_TYPES = [ + ("engine", "Engine"), + ("car", "Car"), + ("equipment", "Equipment"), + ("other", "Other") ] diff --git a/dcc/dcc/urls.py b/dcc/dcc/urls.py index 955fc55..fb5b669 100644 --- a/dcc/dcc/urls.py +++ b/dcc/dcc/urls.py @@ -21,6 +21,8 @@ from django.urls import include, path from roster import urls as roster_urls from driver import urls as driver_urls +admin.site.site_header = "Trains assets manager" + urlpatterns = [ path('ht/', include('health_check.urls')), path('admin/', admin.site.urls), @@ -31,7 +33,7 @@ urlpatterns = [ # if settings.DEBUG: # from django.views.generic import TemplateView # from rest_framework.schemas import get_schema_view -# +# # urlpatterns += [ # path('swagger/', TemplateView.as_view( # template_name='swagger.html', diff --git a/dcc/metadata/admin.py b/dcc/metadata/admin.py index 1c3f400..119d02b 100644 --- a/dcc/metadata/admin.py +++ b/dcc/metadata/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from metadata.models import ( - Decoder, Manufacturer, Company, Tag, RollingStockType) + Decoder, Scale, Manufacturer, Company, Tag, RollingStockType) @admin.register(Decoder) @@ -10,6 +10,12 @@ class DecoderAdmin(admin.ModelAdmin): list_filter = ('manufacturer', 'interface') +@admin.register(Scale) +class ScaleAdmin(admin.ModelAdmin): + list_display = ('scale', 'ratio', 'gauge') + list_filter = ('ratio', 'gauge') + + @admin.register(Company) class CompanyAdmin(admin.ModelAdmin): readonly_fields = ('logo_thumbnail',) diff --git a/dcc/metadata/migrations/0001_initial.py b/dcc/metadata/migrations/0001_initial.py index c3e1d3c..09ced5a 100644 --- a/dcc/metadata/migrations/0001_initial.py +++ b/dcc/metadata/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.0.2 on 2022-04-01 20:25 +# Generated by Django 4.0.2 on 2022-04-02 14:25 from django.db import migrations, models import django.db.models.deletion @@ -17,7 +17,8 @@ class Migration(migrations.Migration): name='Company', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True)), + ('name', models.CharField(max_length=64, unique=True)), + ('extended_name', models.CharField(max_length=128, unique=True)), ('country', django_countries.fields.CountryField(max_length=2)), ('logo', models.ImageField(blank=True, null=True, upload_to='images/')), ], diff --git a/dcc/metadata/migrations/0002_scale_manufacturer_website_and_more.py b/dcc/metadata/migrations/0002_scale_manufacturer_website_and_more.py new file mode 100644 index 0000000..8e289ad --- /dev/null +++ b/dcc/metadata/migrations/0002_scale_manufacturer_website_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.0.2 on 2022-04-02 16:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Scale', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('scale', models.CharField(max_length=32, unique=True)), + ('ratio', models.CharField(blank=True, max_length=16)), + ('gauge', models.CharField(blank=True, max_length=16)), + ], + ), + migrations.AddField( + model_name='manufacturer', + name='website', + field=models.URLField(blank=True), + ), + migrations.AlterField( + model_name='company', + name='extended_name', + field=models.CharField(blank=True, max_length=128), + ), + ] diff --git a/dcc/metadata/models.py b/dcc/metadata/models.py index 5243bf4..47d6576 100644 --- a/dcc/metadata/models.py +++ b/dcc/metadata/models.py @@ -8,6 +8,7 @@ from dcc.utils import get_image_preview, slugify class Manufacturer(models.Model): name = models.CharField(max_length=128, unique=True) + website = models.URLField(blank=True) logo = models.ImageField( upload_to='images/', null=True, @@ -22,7 +23,8 @@ class Manufacturer(models.Model): class Company(models.Model): - name = models.CharField(max_length=128, unique=True) + name = models.CharField(max_length=64, unique=True) + extended_name = models.CharField(max_length=128, blank=True) country = CountryField() logo = models.ImageField( upload_to='images/', @@ -41,20 +43,13 @@ class Company(models.Model): class Decoder(models.Model): - class Interface(models.IntegerChoices): - NEM651 = 1, "NEM651" - NEM652 = 2, "NEM652" - NEM658 = 3, "PluX" - NEM660 = 4, "21MTC" - NEM662 = 5, "Next18/Next18S" - name = models.CharField(max_length=128, unique=True) manufacturer = models.ForeignKey( Manufacturer, on_delete=models.CASCADE) version = models.CharField(max_length=64, blank=True) interface = models.PositiveSmallIntegerField( - choices=Interface.choices, + choices=settings.DECODER_INTERFACES, null=True, blank=True ) @@ -71,6 +66,15 @@ class Decoder(models.Model): image_thumbnail.short_description = "Preview" +class Scale(models.Model): + scale = models.CharField(max_length=32, unique=True) + ratio = models.CharField(max_length=16, blank=True) + gauge = models.CharField(max_length=16, blank=True) + + def __str__(self): + return str(self.scale) + + class Tag(models.Model): name = models.CharField(max_length=128, unique=True) slug = models.CharField(max_length=128, unique=True) diff --git a/dcc/roster/admin.py b/dcc/roster/admin.py index cada57d..f295015 100644 --- a/dcc/roster/admin.py +++ b/dcc/roster/admin.py @@ -1,7 +1,13 @@ from django.contrib import admin from roster.models import ( - RollingStockImage, RollingStockDocument, Engine, Car, - Equipment, Other) + RollingClass, RollingStock, RollingStockImage, RollingStockDocument) + + +@admin.register(RollingClass) +class RollingClass(admin.ModelAdmin): + list_display = ('__str__', 'type', 'company') + list_filter = ('type', 'company') + search_fields = list_display class RollingStockDocInline(admin.TabularInline): @@ -17,50 +23,32 @@ class RollingStockImageInline(admin.TabularInline): readonly_fields = ('image_thumbnail',) +@admin.register(RollingStock) class RollingStockAdmin(admin.ModelAdmin): inlines = (RollingStockImageInline, RollingStockDocInline) - readonly_fields = ('creation_time', 'updated_time',) - list_display = ('identifier', 'manufacturer', 'sku', 'company') - list_filter = list_display + readonly_fields = ('creation_time', 'updated_time') + list_display = ( + '__str__', 'manufacturer', 'scale', 'sku', 'company', 'country') + list_filter = ('manufacturer', 'scale') search_fields = list_display fieldsets = ( (None, { - 'fields': ('identifier', - 'type', - 'tags', + 'fields': ('rolling_class', + 'road_number', 'manufacturer', + 'scale', 'sku', 'decoder', 'address', - 'company', - 'epoch', + 'era', 'production_year', 'purchase_date', - 'notes') + 'notes', + 'tags') }), ('Audit', { 'classes': ('collapse',), 'fields': ('creation_time', 'updated_time',) }), ) - - -@admin.register(Engine) -class Engine(RollingStockAdmin): - list_display = ('identifier', 'address', 'manufacturer', 'sku', 'company') - - -@admin.register(Car) -class Car(RollingStockAdmin): - pass - - -@admin.register(Equipment) -class Equipment(RollingStockAdmin): - pass - - -@admin.register(Other) -class Other(RollingStockAdmin): - pass diff --git a/dcc/roster/migrations/0001_initial.py b/dcc/roster/migrations/0001_initial.py index 2152455..9ad5c6e 100644 --- a/dcc/roster/migrations/0001_initial.py +++ b/dcc/roster/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.0.2 on 2022-04-01 20:25 +# Generated by Django 4.0.2 on 2022-04-02 14:25 from django.db import migrations, models import django.db.models.deletion @@ -14,12 +14,21 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='Class', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('identifier', models.CharField(max_length=128)), + ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.company')), + ('type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.rollingstocktype')), + ], + ), migrations.CreateModel( name='RollingStock', fields=[ ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('identifier', models.CharField(max_length=128)), - ('address', models.SmallIntegerField(blank=True, default=3, null=True)), + ('road_number', models.CharField(max_length=128)), + ('address', models.SmallIntegerField(blank=True, default=None, null=True)), ('sku', models.CharField(blank=True, max_length=32)), ('epoch', models.CharField(blank=True, max_length=32)), ('production_year', models.SmallIntegerField(blank=True, null=True)), @@ -27,14 +36,13 @@ class Migration(migrations.Migration): ('notes', models.TextField(blank=True)), ('creation_time', models.DateTimeField(auto_now_add=True)), ('updated_time', models.DateTimeField(auto_now=True)), - ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.company')), + ('_class', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='roster.class')), ('decoder', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.decoder')), ('manufacturer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.manufacturer')), ('tags', models.ManyToManyField(blank=True, related_name='rolling_stock', to='metadata.Tag')), ], options={ 'verbose_name_plural': 'Rolling stock', - 'ordering': ['address', 'identifier'], }, ), migrations.CreateModel( @@ -60,36 +68,4 @@ class Migration(migrations.Migration): 'unique_together': {('rolling_stock', 'file')}, }, ), - migrations.CreateModel( - name='Other', - fields=[ - ('rollingstock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='roster.rollingstock')), - ('type', models.ForeignKey(blank=True, limit_choices_to={'category': 'other'}, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.rollingstocktype')), - ], - bases=('roster.rollingstock',), - ), - migrations.CreateModel( - name='Equipment', - fields=[ - ('rollingstock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='roster.rollingstock')), - ('type', models.ForeignKey(blank=True, limit_choices_to={'category': 'equipment'}, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.rollingstocktype')), - ], - bases=('roster.rollingstock',), - ), - migrations.CreateModel( - name='Engine', - fields=[ - ('rollingstock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='roster.rollingstock')), - ('type', models.ForeignKey(blank=True, limit_choices_to={'category': 'engine'}, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.rollingstocktype')), - ], - bases=('roster.rollingstock',), - ), - migrations.CreateModel( - name='Car', - fields=[ - ('rollingstock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='roster.rollingstock')), - ('type', models.ForeignKey(blank=True, limit_choices_to={'category': 'car'}, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.rollingstocktype')), - ], - bases=('roster.rollingstock',), - ), ] diff --git a/dcc/roster/migrations/0002_alter_rollingstock_address.py b/dcc/roster/migrations/0002_alter_rollingstock_address.py deleted file mode 100644 index 6d4d23d..0000000 --- a/dcc/roster/migrations/0002_alter_rollingstock_address.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-01 20:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('roster', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='rollingstock', - name='address', - field=models.SmallIntegerField(blank=True, default=None, null=True), - ), - ] diff --git a/dcc/roster/migrations/0002_rename_class_rollingclass_alter_rollingclass_options_and_more.py b/dcc/roster/migrations/0002_rename_class_rollingclass_alter_rollingclass_options_and_more.py new file mode 100644 index 0000000..f1cbb85 --- /dev/null +++ b/dcc/roster/migrations/0002_rename_class_rollingclass_alter_rollingclass_options_and_more.py @@ -0,0 +1,48 @@ +# Generated by Django 4.0.2 on 2022-04-02 16:18 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0002_scale_manufacturer_website_and_more'), + ('roster', '0001_initial'), + ] + + operations = [ + migrations.RenameModel( + old_name='Class', + new_name='RollingClass', + ), + migrations.AlterModelOptions( + name='rollingclass', + options={'ordering': ['company', 'identifier'], 'verbose_name': 'Class', 'verbose_name_plural': 'Classes'}, + ), + migrations.AlterModelOptions( + name='rollingstock', + options={'ordering': ['rolling_class', 'road_number'], 'verbose_name_plural': 'Rolling stock'}, + ), + migrations.RenameField( + model_name='rollingstock', + old_name='epoch', + new_name='era', + ), + migrations.RemoveField( + model_name='rollingstock', + name='_class', + ), + migrations.AddField( + model_name='rollingstock', + name='rolling_class', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='roster.rollingclass', verbose_name='Class'), + preserve_default=False, + ), + migrations.AddField( + model_name='rollingstock', + name='scale', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='metadata.scale'), + preserve_default=False, + ), + ] diff --git a/dcc/roster/migrations/0003_consistitem_consist.py b/dcc/roster/migrations/0003_consistitem_consist.py deleted file mode 100644 index 6017596..0000000 --- a/dcc/roster/migrations/0003_consistitem_consist.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-02 09:09 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('metadata', '0001_initial'), - ('roster', '0002_alter_rollingstock_address'), - ] - - operations = [ - migrations.CreateModel( - name='ConsistItem', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('rolling_stock', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='roster.rollingstock')), - ], - ), - migrations.CreateModel( - name='Consist', - fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('identifier', models.CharField(max_length=128)), - ('epoch', models.CharField(blank=True, max_length=32)), - ('notes', models.TextField(blank=True)), - ('creation_time', models.DateTimeField(auto_now_add=True)), - ('updated_time', models.DateTimeField(auto_now=True)), - ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='metadata.company')), - ('tags', models.ManyToManyField(blank=True, related_name='consist', to='metadata.Tag')), - ], - ), - ] diff --git a/dcc/roster/migrations/0004_consistitem_consist.py b/dcc/roster/migrations/0004_consistitem_consist.py deleted file mode 100644 index 2cf1d18..0000000 --- a/dcc/roster/migrations/0004_consistitem_consist.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-02 09:13 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('roster', '0003_consistitem_consist'), - ] - - operations = [ - migrations.AddField( - model_name='consistitem', - name='consist', - field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='roster.consist'), - preserve_default=False, - ), - ] diff --git a/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py b/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py deleted file mode 100644 index d4be8cc..0000000 --- a/dcc/roster/migrations/0005_remove_consistitem_consist_and_more.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-02 09:21 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('roster', '0004_consistitem_consist'), - ] - - operations = [ - migrations.RemoveField( - model_name='consistitem', - name='consist', - ), - migrations.RemoveField( - model_name='consistitem', - name='rolling_stock', - ), - migrations.DeleteModel( - name='Consist', - ), - migrations.DeleteModel( - name='ConsistItem', - ), - ] diff --git a/dcc/roster/models.py b/dcc/roster/models.py index fd062f1..2875f3c 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -1,12 +1,13 @@ import os from uuid import uuid4 from django.db import models +from django.urls import reverse # from django.core.files.storage import FileSystemStorage # from django.dispatch import receiver from dcc.utils import get_image_preview from metadata.models import ( - Manufacturer, Decoder, Company, Tag, RollingStockType) + Scale, Manufacturer, Decoder, Company, Tag, RollingStockType) # class OverwriteMixin(FileSystemStorage): # def get_available_name(self, name, max_length): @@ -14,67 +15,66 @@ from metadata.models import ( # return name -class RollingStock(models.Model): - uuid = models.UUIDField( - primary_key=True, default=uuid4, - editable=False) +class RollingClass(models.Model): identifier = models.CharField(max_length=128, unique=False) - tags = models.ManyToManyField( - Tag, - related_name='rolling_stock', - blank=True) - address = models.SmallIntegerField(default=None, null=True, blank=True) - manufacturer = models.ForeignKey( - Manufacturer, on_delete=models.CASCADE, - null=True, blank=True) - sku = models.CharField(max_length=32, blank=True) - decoder = models.ForeignKey( - Decoder, on_delete=models.CASCADE, + type = models.ForeignKey( + RollingStockType, on_delete=models.CASCADE, null=True, blank=True) company = models.ForeignKey( Company, on_delete=models.CASCADE, null=True, blank=True) - epoch = models.CharField(max_length=32, blank=True) + + class Meta: + ordering = ['company', 'identifier'] + verbose_name = "Class" + verbose_name_plural = "Classes" + + def __str__(self): + return "{0} {1}".format(self.company, self.identifier) + + +class RollingStock(models.Model): + uuid = models.UUIDField( + primary_key=True, default=uuid4, + editable=False) + rolling_class = models.ForeignKey( + RollingClass, on_delete=models.CASCADE, + null=False, blank=False, + verbose_name="Class") + road_number = models.CharField(max_length=128, unique=False) + manufacturer = models.ForeignKey( + Manufacturer, on_delete=models.CASCADE, + null=True, blank=True) + scale = models.ForeignKey( + Scale, on_delete=models.CASCADE) + sku = models.CharField(max_length=32, blank=True) + decoder = models.ForeignKey( + Decoder, on_delete=models.CASCADE, + null=True, blank=True) + address = models.SmallIntegerField(default=None, null=True, blank=True) + era = models.CharField(max_length=32, blank=True) production_year = models.SmallIntegerField(null=True, blank=True) purchase_date = models.DateField(null=True, blank=True) notes = models.TextField(blank=True) + tags = models.ManyToManyField( + Tag, + related_name='rolling_stock', + blank=True) creation_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True) class Meta: - ordering = ['address', 'identifier'] + ordering = ['rolling_class', 'road_number'] verbose_name_plural = "Rolling stock" def __str__(self): - return "{0} {1}".format(self.manufacturer, self.identifier) + return "{0} {1}".format(self.rolling_class, self.road_number) + def country(self): + return str(self.rolling_class.company.country) -class Engine(RollingStock): - type = models.ForeignKey( - RollingStockType, on_delete=models.CASCADE, - limit_choices_to={'category': 'engine'}, - null=True, blank=True) - - -class Car(RollingStock): - type = models.ForeignKey( - RollingStockType, on_delete=models.CASCADE, - limit_choices_to={'category': 'car'}, - null=True, blank=True) - - -class Equipment(RollingStock): - type = models.ForeignKey( - RollingStockType, on_delete=models.CASCADE, - limit_choices_to={'category': 'equipment'}, - null=True, blank=True) - - -class Other(RollingStock): - type = models.ForeignKey( - RollingStockType, on_delete=models.CASCADE, - limit_choices_to={'category': 'other'}, - null=True, blank=True) + def company(self): + return str(self.rolling_class.company) class RollingStockDocument(models.Model): From e3da5d05d45d4b3dc8df2b92ae1b790448a6f49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 21:37:16 +0200 Subject: [PATCH 4/9] Fix the API --- dcc/dcc/settings.py | 1 + dcc/metadata/admin.py | 5 ++-- ...ny_options_alter_scale_options_and_more.py | 26 +++++++++++++++++++ .../0004_company_freelance_decoder_sound.py | 23 ++++++++++++++++ ...r_company_freelance_alter_decoder_sound.py | 23 ++++++++++++++++ dcc/metadata/models.py | 8 +++++- dcc/metadata/serializers.py | 22 +++++++++++++++- dcc/roster/admin.py | 9 ++++--- .../0003_rollingstockimage_description.py | 18 +++++++++++++ ..._rollingstockimage_description_and_more.py | 22 ++++++++++++++++ dcc/roster/models.py | 1 + dcc/roster/serializers.py | 18 ++++++++++--- 12 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 dcc/metadata/migrations/0003_alter_company_options_alter_scale_options_and_more.py create mode 100644 dcc/metadata/migrations/0004_company_freelance_decoder_sound.py create mode 100644 dcc/metadata/migrations/0005_alter_company_freelance_alter_decoder_sound.py create mode 100644 dcc/roster/migrations/0003_rollingstockimage_description.py create mode 100644 dcc/roster/migrations/0004_remove_rollingstockimage_description_and_more.py diff --git a/dcc/dcc/settings.py b/dcc/dcc/settings.py index 3475115..a1f3046 100644 --- a/dcc/dcc/settings.py +++ b/dcc/dcc/settings.py @@ -152,6 +152,7 @@ DECODER_INTERFACES = [ ROLLING_STOCK_TYPES = [ ("engine", "Engine"), ("car", "Car"), + ("railcar", "Railcar"), ("equipment", "Equipment"), ("other", "Other") ] diff --git a/dcc/metadata/admin.py b/dcc/metadata/admin.py index 119d02b..7d01f4e 100644 --- a/dcc/metadata/admin.py +++ b/dcc/metadata/admin.py @@ -31,9 +31,10 @@ class ManufacturerAdmin(admin.ModelAdmin): @admin.register(Tag) class TagAdmin(admin.ModelAdmin): readonly_fields = ('slug',) + list_display = ('name', 'slug') @admin.register(RollingStockType) class RollingStockTypeAdmin(admin.ModelAdmin): - list_display = ('type', 'category') - list_filter = list_display + list_display = ('__str__',) + list_filter = ('type', 'category') diff --git a/dcc/metadata/migrations/0003_alter_company_options_alter_scale_options_and_more.py b/dcc/metadata/migrations/0003_alter_company_options_alter_scale_options_and_more.py new file mode 100644 index 0000000..9bd9674 --- /dev/null +++ b/dcc/metadata/migrations/0003_alter_company_options_alter_scale_options_and_more.py @@ -0,0 +1,26 @@ +# Generated by Django 4.0.2 on 2022-04-02 17:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0002_scale_manufacturer_website_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='company', + options={'ordering': ['name'], 'verbose_name_plural': 'Companies'}, + ), + migrations.AlterModelOptions( + name='scale', + options={'ordering': ['scale']}, + ), + migrations.AlterField( + model_name='rollingstocktype', + name='category', + field=models.CharField(choices=[('engine', 'Engine'), ('car', 'Car'), ('railcar', 'Railcar'), ('equipment', 'Equipment'), ('other', 'Other')], max_length=64), + ), + ] diff --git a/dcc/metadata/migrations/0004_company_freelance_decoder_sound.py b/dcc/metadata/migrations/0004_company_freelance_decoder_sound.py new file mode 100644 index 0000000..2d32053 --- /dev/null +++ b/dcc/metadata/migrations/0004_company_freelance_decoder_sound.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.2 on 2022-04-02 17:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0003_alter_company_options_alter_scale_options_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='company', + name='freelance', + field=models.BooleanField(blank=True, default=False, null=True), + ), + migrations.AddField( + model_name='decoder', + name='sound', + field=models.BooleanField(blank=True, default=False, null=True), + ), + ] diff --git a/dcc/metadata/migrations/0005_alter_company_freelance_alter_decoder_sound.py b/dcc/metadata/migrations/0005_alter_company_freelance_alter_decoder_sound.py new file mode 100644 index 0000000..215e18d --- /dev/null +++ b/dcc/metadata/migrations/0005_alter_company_freelance_alter_decoder_sound.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.2 on 2022-04-02 17:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('metadata', '0004_company_freelance_decoder_sound'), + ] + + operations = [ + migrations.AlterField( + model_name='company', + name='freelance', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='decoder', + name='sound', + field=models.BooleanField(default=False), + ), + ] diff --git a/dcc/metadata/models.py b/dcc/metadata/models.py index 47d6576..8b2ede8 100644 --- a/dcc/metadata/models.py +++ b/dcc/metadata/models.py @@ -26,6 +26,7 @@ class Company(models.Model): name = models.CharField(max_length=64, unique=True) extended_name = models.CharField(max_length=128, blank=True) country = CountryField() + freelance = models.BooleanField(default=False) logo = models.ImageField( upload_to='images/', null=True, @@ -33,6 +34,7 @@ class Company(models.Model): class Meta: verbose_name_plural = "Companies" + ordering = ['name'] def __str__(self): return self.name @@ -53,6 +55,7 @@ class Decoder(models.Model): null=True, blank=True ) + sound = models.BooleanField(default=False) image = models.ImageField( upload_to='images/', null=True, @@ -71,6 +74,9 @@ class Scale(models.Model): ratio = models.CharField(max_length=16, blank=True) gauge = models.CharField(max_length=16, blank=True) + class Meta: + ordering = ['scale'] + def __str__(self): return str(self.scale) @@ -97,4 +103,4 @@ class RollingStockType(models.Model): unique_together = ('category', 'type') def __str__(self): - return "{0}".format(self.type) + return "{0} {1}".format(self.type, self.category) diff --git a/dcc/metadata/serializers.py b/dcc/metadata/serializers.py index d63fb3c..596ba2a 100644 --- a/dcc/metadata/serializers.py +++ b/dcc/metadata/serializers.py @@ -1,5 +1,13 @@ from rest_framework import serializers -from metadata.models import Manufacturer, Company, Decoder +from metadata.models import ( + RollingStockType, Scale, Manufacturer, + Company, Decoder, Tag) + + +class RollingStockTypeSerializer(serializers.ModelSerializer): + class Meta: + model = RollingStockType + fields = "__all__" class ManufacturerSerializer(serializers.ModelSerializer): @@ -8,6 +16,12 @@ class ManufacturerSerializer(serializers.ModelSerializer): fields = "__all__" +class ScaleSerializer(serializers.ModelSerializer): + class Meta: + model = Scale + fields = "__all__" + + class CompanySerializer(serializers.ModelSerializer): class Meta: model = Company @@ -20,3 +34,9 @@ class DecoderSerializer(serializers.ModelSerializer): class Meta: model = Decoder fields = "__all__" + + +class TagSerializer(serializers.ModelSerializer): + class Meta: + model = Tag + fields = "__all__" diff --git a/dcc/roster/admin.py b/dcc/roster/admin.py index f295015..7acc238 100644 --- a/dcc/roster/admin.py +++ b/dcc/roster/admin.py @@ -6,7 +6,7 @@ from roster.models import ( @admin.register(RollingClass) class RollingClass(admin.ModelAdmin): list_display = ('__str__', 'type', 'company') - list_filter = ('type', 'company') + list_filter = ('company', 'type__category', 'type') search_fields = list_display @@ -28,8 +28,11 @@ class RollingStockAdmin(admin.ModelAdmin): inlines = (RollingStockImageInline, RollingStockDocInline) readonly_fields = ('creation_time', 'updated_time') list_display = ( - '__str__', 'manufacturer', 'scale', 'sku', 'company', 'country') - list_filter = ('manufacturer', 'scale') + '__str__', 'address', 'manufacturer', + 'scale', 'sku', 'company', 'country') + list_filter = ( + 'rolling_class__type__category', 'rolling_class__type', + 'scale', 'manufacturer') search_fields = list_display fieldsets = ( diff --git a/dcc/roster/migrations/0003_rollingstockimage_description.py b/dcc/roster/migrations/0003_rollingstockimage_description.py new file mode 100644 index 0000000..7d991e1 --- /dev/null +++ b/dcc/roster/migrations/0003_rollingstockimage_description.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.2 on 2022-04-02 17:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0002_rename_class_rollingclass_alter_rollingclass_options_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='rollingstockimage', + name='description', + field=models.CharField(blank=True, max_length=256), + ), + ] diff --git a/dcc/roster/migrations/0004_remove_rollingstockimage_description_and_more.py b/dcc/roster/migrations/0004_remove_rollingstockimage_description_and_more.py new file mode 100644 index 0000000..ca7dd75 --- /dev/null +++ b/dcc/roster/migrations/0004_remove_rollingstockimage_description_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 4.0.2 on 2022-04-02 17:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0003_rollingstockimage_description'), + ] + + operations = [ + migrations.RemoveField( + model_name='rollingstockimage', + name='description', + ), + migrations.AddField( + model_name='rollingclass', + name='description', + field=models.CharField(blank=True, max_length=256), + ), + ] diff --git a/dcc/roster/models.py b/dcc/roster/models.py index 2875f3c..df1aa80 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -20,6 +20,7 @@ class RollingClass(models.Model): type = models.ForeignKey( RollingStockType, on_delete=models.CASCADE, null=True, blank=True) + description = models.CharField(max_length=256, blank=True) company = models.ForeignKey( Company, on_delete=models.CASCADE, null=True, blank=True) diff --git a/dcc/roster/serializers.py b/dcc/roster/serializers.py index 1d345ee..3288ca0 100644 --- a/dcc/roster/serializers.py +++ b/dcc/roster/serializers.py @@ -1,13 +1,25 @@ from rest_framework import serializers -from roster.models import RollingStock +from roster.models import RollingClass, RollingStock from metadata.serializers import ( - ManufacturerSerializer, CompanySerializer, DecoderSerializer) + RollingStockTypeSerializer, ManufacturerSerializer, ScaleSerializer, + CompanySerializer, DecoderSerializer, TagSerializer) + + +class RollingClassSerializer(serializers.ModelSerializer): + company = CompanySerializer() + type = RollingStockTypeSerializer() + + class Meta: + model = RollingClass + fields = "__all__" class RollingStockSerializer(serializers.ModelSerializer): + rolling_class = RollingClassSerializer() manufacturer = ManufacturerSerializer() decoder = DecoderSerializer() - company = CompanySerializer() + scale = ScaleSerializer() + tags = TagSerializer(many=True) class Meta: model = RollingStock From d0321d7d56f7c74599822c9f636dae3419e8a460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 21:40:45 +0200 Subject: [PATCH 5/9] Update submodules --- arduino/CommandStation-EX | 2 +- arduino/WebThrottle-EX | 2 +- arduino/arduino-cli | 2 +- arduino/dcc-ex.github.io | 2 +- arduino/vim-arduino | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arduino/CommandStation-EX b/arduino/CommandStation-EX index bd9a045..c47dd10 160000 --- a/arduino/CommandStation-EX +++ b/arduino/CommandStation-EX @@ -1 +1 @@ -Subproject commit bd9a04572de75744dc2f15ac090ec959d7a09a29 +Subproject commit c47dd101a5587fb0bb1dd5602adc0002aebc2f21 diff --git a/arduino/WebThrottle-EX b/arduino/WebThrottle-EX index 37dcc1e..ca33f6a 160000 --- a/arduino/WebThrottle-EX +++ b/arduino/WebThrottle-EX @@ -1 +1 @@ -Subproject commit 37dcc1e9c118c4b324d0ffeb03c6e60d4bb2a2b4 +Subproject commit ca33f6a1e34b09d1fe872eafc810371f53336ec1 diff --git a/arduino/arduino-cli b/arduino/arduino-cli index 10107d2..0364ce3 160000 --- a/arduino/arduino-cli +++ b/arduino/arduino-cli @@ -1 +1 @@ -Subproject commit 10107d2407c2d9997310fc2e0f22dfd15d48e9a8 +Subproject commit 0364ce35894217a12b0131f1fb2282bb2d2472d9 diff --git a/arduino/dcc-ex.github.io b/arduino/dcc-ex.github.io index ab9ae58..a4367c9 160000 --- a/arduino/dcc-ex.github.io +++ b/arduino/dcc-ex.github.io @@ -1 +1 @@ -Subproject commit ab9ae58cf806a306593f42354c372a261502d452 +Subproject commit a4367c9df082257a34d7cde8a0a1baa118aea143 diff --git a/arduino/vim-arduino b/arduino/vim-arduino index 3933f67..bf371b9 160000 --- a/arduino/vim-arduino +++ b/arduino/vim-arduino @@ -1 +1 @@ -Subproject commit 3933f675698615b137027ad842e326a3bc5888be +Subproject commit bf371b96905958cfa7929ef40fd35a0d6a412d86 From 6478800f7717f0ba2c4ca5393d0bd135ce1628fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 22:53:06 +0200 Subject: [PATCH 6/9] Update simulator --- .../CommandStation-EX-uno-509014b.elf | Bin 192056 -> 0 bytes .../CommandStation-EX-uno-c47dd10.elf | Bin 0 -> 192104 bytes daemons/simulator/README.md | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100755 daemons/simulator/CommandStation-EX-uno-509014b.elf create mode 100755 daemons/simulator/CommandStation-EX-uno-c47dd10.elf diff --git a/daemons/simulator/CommandStation-EX-uno-509014b.elf b/daemons/simulator/CommandStation-EX-uno-509014b.elf deleted file mode 100755 index 2ddf862b88f202fda2d973f5d4af6f8beec54d17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192056 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 z 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 z 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 diff --git a/daemons/simulator/CommandStation-EX-uno-c47dd10.elf b/daemons/simulator/CommandStation-EX-uno-c47dd10.elf new file mode 100755 index 0000000000000000000000000000000000000000..7e500c276cb44f2f03e3ea11bf752b16bd435cdb GIT binary patch literal 192104 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 Date: Sat, 2 Apr 2022 22:58:42 +0200 Subject: [PATCH 7/9] Run black --- dcc/consist/admin.py | 44 +++++++++----- dcc/consist/apps.py | 4 +- dcc/consist/models.py | 24 +++----- dcc/dcc/asgi.py | 2 +- dcc/dcc/parsers.py | 2 +- dcc/dcc/settings.py | 112 ++++++++++++++++++------------------ dcc/dcc/urls.py | 8 +-- dcc/dcc/utils.py | 7 ++- dcc/dcc/wsgi.py | 2 +- dcc/driver/apps.py | 5 +- dcc/driver/connector.py | 14 +++-- dcc/driver/health.py | 8 ++- dcc/driver/models.py | 3 +- dcc/driver/serializers.py | 5 +- dcc/driver/urls.py | 12 ++-- dcc/driver/views.py | 61 ++++++++++++-------- dcc/manage.py | 4 +- dcc/metadata/admin.py | 32 ++++++----- dcc/metadata/apps.py | 4 +- dcc/metadata/models.py | 35 +++++------ dcc/metadata/serializers.py | 9 ++- dcc/roster/admin.py | 78 ++++++++++++++++--------- dcc/roster/apps.py | 4 +- dcc/roster/models.py | 72 +++++++++++------------ dcc/roster/serializers.py | 9 ++- dcc/roster/urls.py | 11 ++-- dcc/roster/views.py | 6 +- 27 files changed, 318 insertions(+), 259 deletions(-) diff --git a/dcc/consist/admin.py b/dcc/consist/admin.py index ffa3a48..679caa6 100644 --- a/dcc/consist/admin.py +++ b/dcc/consist/admin.py @@ -8,28 +8,42 @@ class ConsistItemInline(SortableInlineAdminMixin, admin.TabularInline): model = ConsistItem min_num = 1 extra = 0 - readonly_fields = ('address', 'type', 'company', 'era') + readonly_fields = ("address", "type", "company", "era") @admin.register(Consist) class ConsistAdmin(admin.ModelAdmin): inlines = (ConsistItemInline,) - readonly_fields = ('creation_time', 'updated_time',) - list_display = ('identifier', 'company', 'era') + readonly_fields = ( + "creation_time", + "updated_time", + ) + list_display = ("identifier", "company", "era") list_filter = list_display search_fields = list_display fieldsets = ( - (None, { - 'fields': ('identifier', - 'consist_address', - 'company', - 'era', - 'notes', - 'tags') - }), - ('Audit', { - 'classes': ('collapse',), - 'fields': ('creation_time', 'updated_time',) - }), + ( + None, + { + "fields": ( + "identifier", + "consist_address", + "company", + "era", + "notes", + "tags", + ) + }, + ), + ( + "Audit", + { + "classes": ("collapse",), + "fields": ( + "creation_time", + "updated_time", + ), + }, + ), ) diff --git a/dcc/consist/apps.py b/dcc/consist/apps.py index 5f3aa65..1cf6149 100644 --- a/dcc/consist/apps.py +++ b/dcc/consist/apps.py @@ -2,5 +2,5 @@ from django.apps import AppConfig class ConsistConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'consist' + default_auto_field = "django.db.models.BigAutoField" + name = "consist" diff --git a/dcc/consist/models.py b/dcc/consist/models.py index 16f4fc5..4673910 100644 --- a/dcc/consist/models.py +++ b/dcc/consist/models.py @@ -6,19 +6,15 @@ from roster.models import RollingStock class Consist(models.Model): - uuid = models.UUIDField( - primary_key=True, default=uuid4, - editable=False) + uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) identifier = models.CharField(max_length=128, unique=False) - tags = models.ManyToManyField( - Tag, - related_name='consist', - blank=True) + tags = models.ManyToManyField(Tag, related_name="consist", blank=True) consist_address = models.SmallIntegerField( - default=None, null=True, blank=True) + default=None, null=True, blank=True + ) company = models.ForeignKey( - Company, on_delete=models.CASCADE, - null=True, blank=True) + Company, on_delete=models.CASCADE, null=True, blank=True + ) era = models.CharField(max_length=32, blank=True) notes = models.TextField(blank=True) creation_time = models.DateTimeField(auto_now_add=True) @@ -29,14 +25,12 @@ class Consist(models.Model): class ConsistItem(models.Model): - consist = models.ForeignKey( - Consist, on_delete=models.CASCADE) - rolling_stock = models.ForeignKey( - RollingStock, on_delete=models.CASCADE) + consist = models.ForeignKey(Consist, on_delete=models.CASCADE) + rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE) order = models.PositiveIntegerField(default=0, blank=False, null=False) class Meta(object): - ordering = ['order'] + ordering = ["order"] def __str__(self): return "{0}".format(self.rolling_stock) diff --git a/dcc/dcc/asgi.py b/dcc/dcc/asgi.py index 0db25d5..b25b7d7 100644 --- a/dcc/dcc/asgi.py +++ b/dcc/dcc/asgi.py @@ -11,6 +11,6 @@ import os from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dcc.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dcc.settings") application = get_asgi_application() diff --git a/dcc/dcc/parsers.py b/dcc/dcc/parsers.py index f46c972..29755d0 100644 --- a/dcc/dcc/parsers.py +++ b/dcc/dcc/parsers.py @@ -2,7 +2,7 @@ from rest_framework.parsers import BaseParser class PlainTextParser(BaseParser): - media_type = 'text/plain' + media_type = "text/plain" def parse(self, stream, media_type=None, parser_context=None): return stream.read() diff --git a/dcc/dcc/settings.py b/dcc/dcc/settings.py index a1f3046..a87be4f 100644 --- a/dcc/dcc/settings.py +++ b/dcc/dcc/settings.py @@ -21,7 +21,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-1fgtf05rwp0qp05@ef@a7%x#o+t6vk6063py=vhdmut0j!8s4u' +SECRET_KEY = ( + "django-insecure-1fgtf05rwp0qp05@ef@a7%x#o+t6vk6063py=vhdmut0j!8s4u" +) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -32,63 +34,63 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'health_check', - 'health_check.db', - 'django_countries', - 'solo', - 'rest_framework', - 'adminsortable2', - 'dcc', - 'driver', - 'metadata', - 'roster', - 'consist', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "health_check", + "health_check.db", + "django_countries", + "solo", + "rest_framework", + "adminsortable2", + "dcc", + "driver", + "metadata", + "roster", + "consist", ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", # 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = 'dcc.urls' +ROOT_URLCONF = "dcc.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", ], }, }, ] -WSGI_APPLICATION = 'dcc.wsgi.application' +WSGI_APPLICATION = "dcc.wsgi.application" # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", } } @@ -98,16 +100,16 @@ DATABASES = { AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] @@ -115,9 +117,9 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'UTC' +TIME_ZONE = "UTC" USE_I18N = True @@ -127,26 +129,26 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ -STATIC_URL = 'static/' +STATIC_URL = "static/" # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" -MEDIA_URL = 'media/' -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = "media/" +MEDIA_ROOT = os.path.join(BASE_DIR, "media") COUNTRIES_OVERRIDE = { - 'ZZ': "Freelance", + "ZZ": "Freelance", } DECODER_INTERFACES = [ - (1, "NEM651"), - (2, "NEM652"), - (3, "PluX"), - (4, "21MTC"), - (5, "Next18/Next18S") + (1, "NEM651"), + (2, "NEM652"), + (3, "PluX"), + (4, "21MTC"), + (5, "Next18/Next18S"), ] ROLLING_STOCK_TYPES = [ @@ -154,5 +156,5 @@ ROLLING_STOCK_TYPES = [ ("car", "Car"), ("railcar", "Railcar"), ("equipment", "Equipment"), - ("other", "Other") + ("other", "Other"), ] diff --git a/dcc/dcc/urls.py b/dcc/dcc/urls.py index fb5b669..69ba47b 100644 --- a/dcc/dcc/urls.py +++ b/dcc/dcc/urls.py @@ -24,10 +24,10 @@ from driver import urls as driver_urls admin.site.site_header = "Trains assets manager" urlpatterns = [ - path('ht/', include('health_check.urls')), - path('admin/', admin.site.urls), - path('api/v1/roster/', include(roster_urls)), - path('api/v1/dcc/', include(driver_urls)), + path("ht/", include("health_check.urls")), + path("admin/", admin.site.urls), + path("api/v1/roster/", include(roster_urls)), + path("api/v1/dcc/", include(driver_urls)), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # if settings.DEBUG: diff --git a/dcc/dcc/utils.py b/dcc/dcc/utils.py index a2b6f59..e97769e 100644 --- a/dcc/dcc/utils.py +++ b/dcc/dcc/utils.py @@ -5,12 +5,13 @@ from django.utils.text import slugify as django_slugify def get_image_preview(url): return format_html( '' % url) + 'background-color: #eee;" />' % url + ) def slugify(string, custom_separator=None): # Make slug 'flat', both '-' and '_' are replaced with '-' - string = django_slugify(string).replace('_', '-') + string = django_slugify(string).replace("_", "-") if custom_separator is not None: - string = string.replace('-', custom_separator) + string = string.replace("-", custom_separator) return string diff --git a/dcc/dcc/wsgi.py b/dcc/dcc/wsgi.py index 8435ef1..4b7e8c5 100644 --- a/dcc/dcc/wsgi.py +++ b/dcc/dcc/wsgi.py @@ -11,6 +11,6 @@ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dcc.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dcc.settings") application = get_wsgi_application() diff --git a/dcc/driver/apps.py b/dcc/driver/apps.py index 27eca5a..0c77fc7 100644 --- a/dcc/driver/apps.py +++ b/dcc/driver/apps.py @@ -3,9 +3,10 @@ from health_check.plugins import plugin_dir class DriverConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'driver' + default_auto_field = "django.db.models.BigAutoField" + name = "driver" def ready(self): from driver.health import DriverHealthCheck + plugin_dir.register(DriverHealthCheck) diff --git a/dcc/driver/connector.py b/dcc/driver/connector.py index d195b41..def3c7e 100644 --- a/dcc/driver/connector.py +++ b/dcc/driver/connector.py @@ -8,7 +8,7 @@ class Connector: self.config = DriverConfiguration.get_solo() def __send_data(self, message): - resp = b'' + resp = b"" # convert to binary if str is received if isinstance(message, str): message = message.encode() @@ -30,10 +30,12 @@ class Connector: def ops(self, address, data, function=False): if function: message = "".format( - address, data['function'], data['state']) + address, data["function"], data["state"] + ) else: message = "".format( - address, data['speed'], data['direction']) + address, data["speed"], data["direction"] + ) self.__send_data(message) def infra(self, data): @@ -43,9 +45,9 @@ class Connector: track = "" if data["power"]: - self.__send_data('<1{}>'.format(track)) + self.__send_data("<1{}>".format(track)) else: - self.__send_data('<0{}>'.format(track)) + self.__send_data("<0{}>".format(track)) def emergency(self): - self.__send_data('') + self.__send_data("") diff --git a/dcc/driver/health.py b/dcc/driver/health.py index 75e09f9..b715b1a 100644 --- a/dcc/driver/health.py +++ b/dcc/driver/health.py @@ -1,6 +1,8 @@ from health_check.backends import BaseHealthCheckBackend -from health_check.exceptions import (ServiceUnavailable, - ServiceReturnedUnexpectedResult) +from health_check.exceptions import ( + ServiceUnavailable, + ServiceReturnedUnexpectedResult, +) from driver.connector import Connector @@ -10,7 +12,7 @@ class DriverHealthCheck(BaseHealthCheckBackend): def check_status(self): try: - Connector().passthrough(b'') + Connector().passthrough(b"") except ConnectionRefusedError as e: self.add_error(ServiceUnavailable("IOError"), e) except Exception as e: diff --git a/dcc/driver/models.py b/dcc/driver/models.py index 972ca19..f5a72df 100644 --- a/dcc/driver/models.py +++ b/dcc/driver/models.py @@ -4,7 +4,8 @@ from solo.models import SingletonModel class DriverConfiguration(SingletonModel): remote_host = models.GenericIPAddressField( - protocol="IPv4", default="192.168.4.1") + protocol="IPv4", default="192.168.4.1" + ) remote_port = models.SmallIntegerField(default=2560) timeout = models.SmallIntegerField(default=250) diff --git a/dcc/driver/serializers.py b/dcc/driver/serializers.py index 19b5ac1..68af6ce 100644 --- a/dcc/driver/serializers.py +++ b/dcc/driver/serializers.py @@ -14,5 +14,6 @@ class CabSerializer(serializers.Serializer): class InfraSerializer(serializers.Serializer): power = serializers.BooleanField(required=True) track = serializers.ChoiceField( - choices=('main', 'prog', 'join', 'MAIN', 'PROG', 'JOIN'), - required=False) + choices=("main", "prog", "join", "MAIN", "PROG", "JOIN"), + required=False, + ) diff --git a/dcc/driver/urls.py b/dcc/driver/urls.py index 64a8e26..d8a52f7 100644 --- a/dcc/driver/urls.py +++ b/dcc/driver/urls.py @@ -2,10 +2,10 @@ from django.urls import path from driver.views import SendCommand, Function, Cab, Emergency, Infra, Test urlpatterns = [ - path('test', Test.as_view()), - path('emergency', Emergency.as_view()), - path('infra', Infra.as_view()), - path('command', SendCommand.as_view()), - path('/cab', Cab.as_view()), - path('/function', Function.as_view()), + path("test", Test.as_view()), + path("emergency", Emergency.as_view()), + path("infra", Infra.as_view()), + path("command", SendCommand.as_view()), + path("/cab", Cab.as_view()), + path("/function", Function.as_view()), ] diff --git a/dcc/driver/views.py b/dcc/driver/views.py index 1b9236b..ed51f7a 100644 --- a/dcc/driver/views.py +++ b/dcc/driver/views.py @@ -7,7 +7,10 @@ from rest_framework.response import Response from dcc.parsers import PlainTextParser from driver.connector import Connector from driver.serializers import ( - FunctionSerializer, CabSerializer, InfraSerializer) + FunctionSerializer, + CabSerializer, + InfraSerializer, +) from roster.models import RollingStock @@ -15,10 +18,12 @@ def addresschecker(f): """ Check if DCC address does exist in the database """ + def addresslookup(request, address, *args): if not RollingStock.objects.filter(address=address): raise Http404 return f(request, address, *args) + return addresslookup @@ -26,32 +31,38 @@ class Test(APIView): """ Send a test command """ + parser_classes = [PlainTextParser] def get(self, request): response = Connector().passthrough("") - return Response({"response": response.decode()}, - status=status.HTTP_202_ACCEPTED) + return Response( + {"response": response.decode()}, status=status.HTTP_202_ACCEPTED + ) class SendCommand(APIView): """ Command passthrough """ + parser_classes = [PlainTextParser] def put(self, request): data = request.data if not data: - raise serializers.ValidationError({ - "error": "a string is expected"}) + raise serializers.ValidationError( + {"error": "a string is expected"} + ) cmd = data.decode().strip() if not (cmd.startswith("<") and cmd.endswith(">")): - raise serializers.ValidationError({ - "error": "please provide a valid command"}) + raise serializers.ValidationError( + {"error": "please provide a valid command"} + ) response = Connector().passthrough(cmd) - return Response({"response": response.decode()}, - status=status.HTTP_202_ACCEPTED) + return Response( + {"response": response.decode()}, status=status.HTTP_202_ACCEPTED + ) @method_decorator(addresschecker, name="put") @@ -59,15 +70,14 @@ class Function(APIView): """ Send "Function" commands to a valid DCC address """ + def put(self, request, address): serializer = FunctionSerializer(data=request.data) if serializer.is_valid(): Connector().ops(address, serializer.data, function=True) - return Response(serializer.data, - status=status.HTTP_202_ACCEPTED) + return Response(serializer.data, status=status.HTTP_202_ACCEPTED) - return Response(serializer.errors, - status=status.HTTP_400_BAD_REQUEST) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @method_decorator(addresschecker, name="put") @@ -75,42 +85,43 @@ class Cab(APIView): """ Send "Cab" commands to a valid DCC address """ + def put(self, request, address): serializer = CabSerializer(data=request.data) if serializer.is_valid(): Connector().ops(address, serializer.data) - return Response(serializer.data, - status=status.HTTP_202_ACCEPTED) + return Response(serializer.data, status=status.HTTP_202_ACCEPTED) - return Response(serializer.errors, - status=status.HTTP_400_BAD_REQUEST) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class Infra(APIView): """ Send "Infra" commands to a valid DCC address """ + def put(self, request): serializer = InfraSerializer(data=request.data) if serializer.is_valid(): Connector().infra(serializer.data) - return Response(serializer.data, - status=status.HTTP_202_ACCEPTED) + return Response(serializer.data, status=status.HTTP_202_ACCEPTED) - return Response(serializer.errors, - status=status.HTTP_400_BAD_REQUEST) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class Emergency(APIView): """ Send an "Emergency" stop, no matter the HTTP method used """ + def put(self, request): Connector().emergency() - return Response({"response": "emergency stop"}, - status=status.HTTP_202_ACCEPTED) + return Response( + {"response": "emergency stop"}, status=status.HTTP_202_ACCEPTED + ) def get(self, request): Connector().emergency() - return Response({"response": "emergency stop"}, - status=status.HTTP_202_ACCEPTED) + return Response( + {"response": "emergency stop"}, status=status.HTTP_202_ACCEPTED + ) diff --git a/dcc/manage.py b/dcc/manage.py index 88b1b9e..20ea1dc 100755 --- a/dcc/manage.py +++ b/dcc/manage.py @@ -6,7 +6,7 @@ import sys def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dcc.settings') + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dcc.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -18,5 +18,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/dcc/metadata/admin.py b/dcc/metadata/admin.py index 7d01f4e..fdedd1a 100644 --- a/dcc/metadata/admin.py +++ b/dcc/metadata/admin.py @@ -1,40 +1,46 @@ from django.contrib import admin from metadata.models import ( - Decoder, Scale, Manufacturer, Company, Tag, RollingStockType) + Decoder, + Scale, + Manufacturer, + Company, + Tag, + RollingStockType, +) @admin.register(Decoder) class DecoderAdmin(admin.ModelAdmin): - readonly_fields = ('image_thumbnail',) - list_display = ('__str__', 'interface') - list_filter = ('manufacturer', 'interface') + readonly_fields = ("image_thumbnail",) + list_display = ("__str__", "interface") + list_filter = ("manufacturer", "interface") @admin.register(Scale) class ScaleAdmin(admin.ModelAdmin): - list_display = ('scale', 'ratio', 'gauge') - list_filter = ('ratio', 'gauge') + list_display = ("scale", "ratio", "gauge") + list_filter = ("ratio", "gauge") @admin.register(Company) class CompanyAdmin(admin.ModelAdmin): - readonly_fields = ('logo_thumbnail',) - list_display = ('name', 'country') + readonly_fields = ("logo_thumbnail",) + list_display = ("name", "country") list_filter = list_display @admin.register(Manufacturer) class ManufacturerAdmin(admin.ModelAdmin): - readonly_fields = ('logo_thumbnail',) + readonly_fields = ("logo_thumbnail",) @admin.register(Tag) class TagAdmin(admin.ModelAdmin): - readonly_fields = ('slug',) - list_display = ('name', 'slug') + readonly_fields = ("slug",) + list_display = ("name", "slug") @admin.register(RollingStockType) class RollingStockTypeAdmin(admin.ModelAdmin): - list_display = ('__str__',) - list_filter = ('type', 'category') + list_display = ("__str__",) + list_filter = ("type", "category") diff --git a/dcc/metadata/apps.py b/dcc/metadata/apps.py index 1d731c9..e41215d 100644 --- a/dcc/metadata/apps.py +++ b/dcc/metadata/apps.py @@ -2,5 +2,5 @@ from django.apps import AppConfig class MetadataConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'metadata' + default_auto_field = "django.db.models.BigAutoField" + name = "metadata" diff --git a/dcc/metadata/models.py b/dcc/metadata/models.py index 8b2ede8..58ed46d 100644 --- a/dcc/metadata/models.py +++ b/dcc/metadata/models.py @@ -9,16 +9,14 @@ from dcc.utils import get_image_preview, slugify class Manufacturer(models.Model): name = models.CharField(max_length=128, unique=True) website = models.URLField(blank=True) - logo = models.ImageField( - upload_to='images/', - null=True, - blank=True) + logo = models.ImageField(upload_to="images/", null=True, blank=True) def __str__(self): return self.name def logo_thumbnail(self): return get_image_preview(self.logo.url) + logo_thumbnail.short_description = "Preview" @@ -27,45 +25,37 @@ class Company(models.Model): extended_name = models.CharField(max_length=128, blank=True) country = CountryField() freelance = models.BooleanField(default=False) - logo = models.ImageField( - upload_to='images/', - null=True, - blank=True) + logo = models.ImageField(upload_to="images/", null=True, blank=True) class Meta: verbose_name_plural = "Companies" - ordering = ['name'] + ordering = ["name"] def __str__(self): return self.name def logo_thumbnail(self): return get_image_preview(self.logo.url) + logo_thumbnail.short_description = "Preview" class Decoder(models.Model): name = models.CharField(max_length=128, unique=True) - manufacturer = models.ForeignKey( - Manufacturer, - on_delete=models.CASCADE) + manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) version = models.CharField(max_length=64, blank=True) interface = models.PositiveSmallIntegerField( - choices=settings.DECODER_INTERFACES, - null=True, - blank=True + choices=settings.DECODER_INTERFACES, null=True, blank=True ) sound = models.BooleanField(default=False) - image = models.ImageField( - upload_to='images/', - null=True, - blank=True) + image = models.ImageField(upload_to="images/", null=True, blank=True) def __str__(self): return "{0} - {1}".format(self.manufacturer, self.name) def image_thumbnail(self): return get_image_preview(self.image.url) + image_thumbnail.short_description = "Preview" @@ -75,7 +65,7 @@ class Scale(models.Model): gauge = models.CharField(max_length=16, blank=True) class Meta: - ordering = ['scale'] + ordering = ["scale"] def __str__(self): return str(self.scale) @@ -97,10 +87,11 @@ def tag_pre_save(sender, instance, **kwargs): class RollingStockType(models.Model): type = models.CharField(max_length=64) category = models.CharField( - max_length=64, choices=settings.ROLLING_STOCK_TYPES) + max_length=64, choices=settings.ROLLING_STOCK_TYPES + ) class Meta(object): - unique_together = ('category', 'type') + unique_together = ("category", "type") def __str__(self): return "{0} {1}".format(self.type, self.category) diff --git a/dcc/metadata/serializers.py b/dcc/metadata/serializers.py index 596ba2a..7dd3e0b 100644 --- a/dcc/metadata/serializers.py +++ b/dcc/metadata/serializers.py @@ -1,7 +1,12 @@ from rest_framework import serializers from metadata.models import ( - RollingStockType, Scale, Manufacturer, - Company, Decoder, Tag) + RollingStockType, + Scale, + Manufacturer, + Company, + Decoder, + Tag, +) class RollingStockTypeSerializer(serializers.ModelSerializer): diff --git a/dcc/roster/admin.py b/dcc/roster/admin.py index 7acc238..37aff2d 100644 --- a/dcc/roster/admin.py +++ b/dcc/roster/admin.py @@ -1,12 +1,16 @@ from django.contrib import admin from roster.models import ( - RollingClass, RollingStock, RollingStockImage, RollingStockDocument) + RollingClass, + RollingStock, + RollingStockImage, + RollingStockDocument, +) @admin.register(RollingClass) class RollingClass(admin.ModelAdmin): - list_display = ('__str__', 'type', 'company') - list_filter = ('company', 'type__category', 'type') + list_display = ("__str__", "type", "company") + list_filter = ("company", "type__category", "type") search_fields = list_display @@ -20,38 +24,58 @@ class RollingStockImageInline(admin.TabularInline): model = RollingStockImage min_num = 0 extra = 0 - readonly_fields = ('image_thumbnail',) + readonly_fields = ("image_thumbnail",) @admin.register(RollingStock) class RollingStockAdmin(admin.ModelAdmin): inlines = (RollingStockImageInline, RollingStockDocInline) - readonly_fields = ('creation_time', 'updated_time') + readonly_fields = ("creation_time", "updated_time") list_display = ( - '__str__', 'address', 'manufacturer', - 'scale', 'sku', 'company', 'country') + "__str__", + "address", + "manufacturer", + "scale", + "sku", + "company", + "country", + ) list_filter = ( - 'rolling_class__type__category', 'rolling_class__type', - 'scale', 'manufacturer') + "rolling_class__type__category", + "rolling_class__type", + "scale", + "manufacturer", + ) search_fields = list_display fieldsets = ( - (None, { - 'fields': ('rolling_class', - 'road_number', - 'manufacturer', - 'scale', - 'sku', - 'decoder', - 'address', - 'era', - 'production_year', - 'purchase_date', - 'notes', - 'tags') - }), - ('Audit', { - 'classes': ('collapse',), - 'fields': ('creation_time', 'updated_time',) - }), + ( + None, + { + "fields": ( + "rolling_class", + "road_number", + "manufacturer", + "scale", + "sku", + "decoder", + "address", + "era", + "production_year", + "purchase_date", + "notes", + "tags", + ) + }, + ), + ( + "Audit", + { + "classes": ("collapse",), + "fields": ( + "creation_time", + "updated_time", + ), + }, + ), ) diff --git a/dcc/roster/apps.py b/dcc/roster/apps.py index 39f52e7..e0172d1 100644 --- a/dcc/roster/apps.py +++ b/dcc/roster/apps.py @@ -2,5 +2,5 @@ from django.apps import AppConfig class RosterConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'roster' + default_auto_field = "django.db.models.BigAutoField" + name = "roster" diff --git a/dcc/roster/models.py b/dcc/roster/models.py index df1aa80..5c99b03 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -2,12 +2,19 @@ import os from uuid import uuid4 from django.db import models from django.urls import reverse + # from django.core.files.storage import FileSystemStorage # from django.dispatch import receiver from dcc.utils import get_image_preview from metadata.models import ( - Scale, Manufacturer, Decoder, Company, Tag, RollingStockType) + Scale, + Manufacturer, + Decoder, + Company, + Tag, + RollingStockType, +) # class OverwriteMixin(FileSystemStorage): # def get_available_name(self, name, max_length): @@ -18,15 +25,15 @@ from metadata.models import ( class RollingClass(models.Model): identifier = models.CharField(max_length=128, unique=False) type = models.ForeignKey( - RollingStockType, on_delete=models.CASCADE, - null=True, blank=True) + RollingStockType, on_delete=models.CASCADE, null=True, blank=True + ) description = models.CharField(max_length=256, blank=True) company = models.ForeignKey( - Company, on_delete=models.CASCADE, - null=True, blank=True) + Company, on_delete=models.CASCADE, null=True, blank=True + ) class Meta: - ordering = ['company', 'identifier'] + ordering = ["company", "identifier"] verbose_name = "Class" verbose_name_plural = "Classes" @@ -35,37 +42,36 @@ class RollingClass(models.Model): class RollingStock(models.Model): - uuid = models.UUIDField( - primary_key=True, default=uuid4, - editable=False) + uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) rolling_class = models.ForeignKey( - RollingClass, on_delete=models.CASCADE, - null=False, blank=False, - verbose_name="Class") + RollingClass, + on_delete=models.CASCADE, + null=False, + blank=False, + verbose_name="Class", + ) road_number = models.CharField(max_length=128, unique=False) manufacturer = models.ForeignKey( - Manufacturer, on_delete=models.CASCADE, - null=True, blank=True) - scale = models.ForeignKey( - Scale, on_delete=models.CASCADE) + Manufacturer, on_delete=models.CASCADE, null=True, blank=True + ) + scale = models.ForeignKey(Scale, on_delete=models.CASCADE) sku = models.CharField(max_length=32, blank=True) decoder = models.ForeignKey( - Decoder, on_delete=models.CASCADE, - null=True, blank=True) + Decoder, on_delete=models.CASCADE, null=True, blank=True + ) address = models.SmallIntegerField(default=None, null=True, blank=True) era = models.CharField(max_length=32, blank=True) production_year = models.SmallIntegerField(null=True, blank=True) purchase_date = models.DateField(null=True, blank=True) notes = models.TextField(blank=True) tags = models.ManyToManyField( - Tag, - related_name='rolling_stock', - blank=True) + Tag, related_name="rolling_stock", blank=True + ) creation_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True) class Meta: - ordering = ['rolling_class', 'road_number'] + ordering = ["rolling_class", "road_number"] verbose_name_plural = "Rolling stock" def __str__(self): @@ -79,16 +85,12 @@ class RollingStock(models.Model): class RollingStockDocument(models.Model): - rolling_stock = models.ForeignKey( - RollingStock, on_delete=models.CASCADE) + rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE) description = models.CharField(max_length=128, blank=True) - file = models.FileField( - upload_to='files/', - null=True, - blank=True) + file = models.FileField(upload_to="files/", null=True, blank=True) class Meta(object): - unique_together = ('rolling_stock', 'file') + unique_together = ("rolling_stock", "file") def __str__(self): return "{0}".format(os.path.basename(self.file.name)) @@ -96,23 +98,21 @@ class RollingStockDocument(models.Model): class RollingStockImage(models.Model): - rolling_stock = models.ForeignKey( - RollingStock, on_delete=models.CASCADE) - image = models.ImageField( - upload_to='images/', - null=True, - blank=True) + rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE) + image = models.ImageField(upload_to="images/", null=True, blank=True) def image_thumbnail(self): return get_image_preview(self.image.url) + image_thumbnail.short_description = "Preview" class Meta(object): - unique_together = ('rolling_stock', 'image') + unique_together = ("rolling_stock", "image") def __str__(self): return "{0}".format(os.path.basename(self.image.name)) + # @receiver(models.signals.post_delete, sender=Cab) # def post_save_image(sender, instance, *args, **kwargs): # try: diff --git a/dcc/roster/serializers.py b/dcc/roster/serializers.py index 3288ca0..228e43a 100644 --- a/dcc/roster/serializers.py +++ b/dcc/roster/serializers.py @@ -1,8 +1,13 @@ from rest_framework import serializers from roster.models import RollingClass, RollingStock from metadata.serializers import ( - RollingStockTypeSerializer, ManufacturerSerializer, ScaleSerializer, - CompanySerializer, DecoderSerializer, TagSerializer) + RollingStockTypeSerializer, + ManufacturerSerializer, + ScaleSerializer, + CompanySerializer, + DecoderSerializer, + TagSerializer, +) class RollingClassSerializer(serializers.ModelSerializer): diff --git a/dcc/roster/urls.py b/dcc/roster/urls.py index afca8f4..87ccf38 100644 --- a/dcc/roster/urls.py +++ b/dcc/roster/urls.py @@ -1,10 +1,9 @@ from django.urls import path -from roster.views import ( - RosterList, RosterGet, RosterAddress, RosterIdentifier) +from roster.views import RosterList, RosterGet, RosterAddress, RosterIdentifier urlpatterns = [ - path('list', RosterList.as_view()), - path('get/', RosterGet.as_view()), - path('address/', RosterAddress.as_view()), - path('identifier/', RosterIdentifier.as_view()), + path("list", RosterList.as_view()), + path("get/", RosterGet.as_view()), + path("address/", RosterAddress.as_view()), + path("identifier/", RosterIdentifier.as_view()), ] diff --git a/dcc/roster/views.py b/dcc/roster/views.py index 6a29409..a11ac45 100644 --- a/dcc/roster/views.py +++ b/dcc/roster/views.py @@ -12,16 +12,16 @@ class RosterList(ListAPIView): class RosterGet(RetrieveAPIView): queryset = RollingStock.objects.all() serializer_class = RollingStockSerializer - lookup_field = 'uuid' + lookup_field = "uuid" class RosterAddress(ListAPIView): queryset = RollingStock.objects.all() serializer_class = RollingStockSerializer - lookup_field = 'address' + lookup_field = "address" class RosterIdentifier(RetrieveAPIView): queryset = RollingStock.objects.all() serializer_class = RollingStockSerializer - lookup_field = 'identifier' + lookup_field = "identifier" From faf44d7c0c4e21a8e9cc78525431815636b4f5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 23:31:32 +0200 Subject: [PATCH 8/9] Add consists API --- dcc/consist/models.py | 6 +++++- dcc/consist/serializers.py | 24 ++++++++++++++++++++++++ dcc/consist/urls.py | 6 ++++++ dcc/consist/views.py | 22 ++++++++++++++++++++-- dcc/dcc/urls.py | 2 ++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 dcc/consist/serializers.py create mode 100644 dcc/consist/urls.py diff --git a/dcc/consist/models.py b/dcc/consist/models.py index 4673910..4db824b 100644 --- a/dcc/consist/models.py +++ b/dcc/consist/models.py @@ -25,7 +25,11 @@ class Consist(models.Model): class ConsistItem(models.Model): - consist = models.ForeignKey(Consist, on_delete=models.CASCADE) + consist = models.ForeignKey( + Consist, + on_delete=models.CASCADE, + related_name="consist_item" + ) rolling_stock = models.ForeignKey(RollingStock, on_delete=models.CASCADE) order = models.PositiveIntegerField(default=0, blank=False, null=False) diff --git a/dcc/consist/serializers.py b/dcc/consist/serializers.py new file mode 100644 index 0000000..947b487 --- /dev/null +++ b/dcc/consist/serializers.py @@ -0,0 +1,24 @@ +from rest_framework import serializers +from consist.models import Consist, ConsistItem + +from metadata.serializers import CompanySerializer, TagSerializer + +# from roster.serializers import RollingStockSerializer + + +class ConsistItemSerializer(serializers.ModelSerializer): + # rolling_stock = RollingStockSerializer() + + class Meta: + model = ConsistItem + fields = ("order", "rolling_stock") + + +class ConsistSerializer(serializers.ModelSerializer): + company = CompanySerializer() + consist_item = ConsistItemSerializer(many=True) + tags = TagSerializer(many=True) + + class Meta: + model = Consist + fields = "__all__" diff --git a/dcc/consist/urls.py b/dcc/consist/urls.py new file mode 100644 index 0000000..af648ca --- /dev/null +++ b/dcc/consist/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from consist.views import ConsistList + +urlpatterns = [ + path("list", ConsistList.as_view()), +] diff --git a/dcc/consist/views.py b/dcc/consist/views.py index 91ea44a..e3fdf06 100644 --- a/dcc/consist/views.py +++ b/dcc/consist/views.py @@ -1,3 +1,21 @@ -from django.shortcuts import render +from rest_framework.generics import ListAPIView, RetrieveAPIView -# Create your views here. +from consist.models import Consist +from consist.serializers import ConsistSerializer + + +class ConsistList(ListAPIView): + queryset = Consist.objects.all() + serializer_class = ConsistSerializer + + +class ConsistGet(RetrieveAPIView): + queryset = Consist.objects.all() + serializer_class = ConsistSerializer + lookup_field = "uuid" + + +# class RosterIdentifier(RetrieveAPIView): +# queryset = RollingStock.objects.all() +# serializer_class = RollingStockSerializer +# lookup_field = "identifier" diff --git a/dcc/dcc/urls.py b/dcc/dcc/urls.py index 69ba47b..34dce49 100644 --- a/dcc/dcc/urls.py +++ b/dcc/dcc/urls.py @@ -18,6 +18,7 @@ from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path +from consist import urls as consist_urls from roster import urls as roster_urls from driver import urls as driver_urls @@ -26,6 +27,7 @@ admin.site.site_header = "Trains assets manager" urlpatterns = [ path("ht/", include("health_check.urls")), path("admin/", admin.site.urls), + path("api/v1/consist/", include(consist_urls)), path("api/v1/roster/", include(roster_urls)), path("api/v1/dcc/", include(driver_urls)), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) From 1b55acd09f4b617f41f4dca1499e6ec0409444fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 2 Apr 2022 23:32:29 +0200 Subject: [PATCH 9/9] Add migrations --- .../0003_alter_consistitem_consist.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 dcc/consist/migrations/0003_alter_consistitem_consist.py diff --git a/dcc/consist/migrations/0003_alter_consistitem_consist.py b/dcc/consist/migrations/0003_alter_consistitem_consist.py new file mode 100644 index 0000000..6a2420f --- /dev/null +++ b/dcc/consist/migrations/0003_alter_consistitem_consist.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.3 on 2022-04-02 21:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('consist', '0002_rename_address_consist_consist_address_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='consistitem', + name='consist', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consist_item', to='consist.consist'), + ), + ]