From 53c0033d8c554b27212a1879ebcacae47fcc5c1d Mon Sep 17 00:00:00 2001 From: Andrew Northall Date: Wed, 1 Nov 2023 06:00:28 +0000 Subject: [PATCH] Migrate cavers field to ManyToManyField --- app/logger/admin.py | 16 ++++- app/logger/migrations/0034_caver.py | 61 +++++++++++++++++++ app/logger/migrations/0035_trip_cavers_new.py | 21 +++++++ .../0036_old_cavers_to_new_cavers.py | 36 +++++++++++ .../migrations/0037_rename_caver_fields.py | 22 +++++++ app/logger/models/trip.py | 30 ++++++++- app/templates/logger/_trip_data_blocks.html | 4 +- app/templates/logger/profile.html | 4 +- 8 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 app/logger/migrations/0034_caver.py create mode 100644 app/logger/migrations/0035_trip_cavers_new.py create mode 100644 app/logger/migrations/0036_old_cavers_to_new_cavers.py create mode 100644 app/logger/migrations/0037_rename_caver_fields.py diff --git a/app/logger/admin.py b/app/logger/admin.py index b5be0c2b..2649810f 100644 --- a/app/logger/admin.py +++ b/app/logger/admin.py @@ -14,6 +14,17 @@ class TripAdminForm(DistanceUnitFormMixin, ModelForm): pass +class CaverInline(TabularInline): + model = Trip.cavers.through + extra = 0 + + def has_add_permission(self, request, obj=None): + return False + + def has_change_permission(self, request, obj=None): + return False + + class TripPhotoInline(TabularInline): model = TripPhoto fk_name = "trip" @@ -29,7 +40,7 @@ def has_add_permission(self, request, obj=None): @admin.register(Trip) class TripAdmin(ModelAdmin): form = TripAdminForm - inlines = [TripPhotoInline] + inlines = [CaverInline, TripPhotoInline] search_fields = ( "cave_name", "cave_entrance", @@ -108,10 +119,9 @@ class TripAdmin(ModelAdmin): }, ), ( - "Attendees", + "Organisations", { "fields": ( - "cavers", "clubs", "expedition", ), diff --git a/app/logger/migrations/0034_caver.py b/app/logger/migrations/0034_caver.py new file mode 100644 index 00000000..28a9bd86 --- /dev/null +++ b/app/logger/migrations/0034_caver.py @@ -0,0 +1,61 @@ +# Generated by Django 4.2.6 on 2023-10-31 17:00 + +import uuid + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("logger", "0033_make_trip_owner_follow_their_trips"), + ] + + operations = [ + migrations.CreateModel( + name="Caver", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=40)), + ( + "added", + models.DateTimeField( + auto_now_add=True, verbose_name="caver added on" + ), + ), + ( + "updated", + models.DateTimeField( + auto_now=True, verbose_name="caver last updated" + ), + ), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="A unique identifier for this caver.", + unique=True, + verbose_name="UUID", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/app/logger/migrations/0035_trip_cavers_new.py b/app/logger/migrations/0035_trip_cavers_new.py new file mode 100644 index 00000000..67af97bb --- /dev/null +++ b/app/logger/migrations/0035_trip_cavers_new.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.6 on 2023-10-31 17:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("logger", "0034_caver"), + ] + + operations = [ + migrations.AddField( + model_name="trip", + name="cavers_new", + field=models.ManyToManyField( + blank=True, + help_text="A list of cavers that were on this trip.", + to="logger.caver", + ), + ), + ] diff --git a/app/logger/migrations/0036_old_cavers_to_new_cavers.py b/app/logger/migrations/0036_old_cavers_to_new_cavers.py new file mode 100644 index 00000000..6dda2611 --- /dev/null +++ b/app/logger/migrations/0036_old_cavers_to_new_cavers.py @@ -0,0 +1,36 @@ +# Generated by Django 4.2.6 on 2023-10-31 17:03 + +from django.db import migrations + + +def migrate_old_cavers_to_new_cavers(apps, schema_editor): + """Migrate old, comma separated text field to new ManyToMany field""" + Trip = apps.get_model("logger", "Trip") + Caver = apps.get_model("logger", "Caver") + + for trip in Trip.objects.all(): + if not trip.cavers: + continue + + caver_names = trip.cavers.split(",") + for caver_name in caver_names: + caver_name = caver_name.strip() + if not caver_name: + continue + + try: + caver = Caver.objects.get(name__iexact=caver_name, user=trip.user) + except Caver.DoesNotExist: + caver = Caver.objects.create(name=caver_name, user=trip.user) + + trip.cavers_new.add(caver) + + +class Migration(migrations.Migration): + dependencies = [ + ("logger", "0035_trip_cavers_new"), + ] + + operations = [ + migrations.RunPython(migrate_old_cavers_to_new_cavers), + ] diff --git a/app/logger/migrations/0037_rename_caver_fields.py b/app/logger/migrations/0037_rename_caver_fields.py new file mode 100644 index 00000000..f478b214 --- /dev/null +++ b/app/logger/migrations/0037_rename_caver_fields.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.6 on 2023-10-31 17:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("logger", "0036_old_cavers_to_new_cavers"), + ] + + operations = [ + migrations.RenameField( + model_name="trip", + old_name="cavers", + new_name="cavers_old", + ), + migrations.RenameField( + model_name="trip", + old_name="cavers_new", + new_name="cavers", + ), + ] diff --git a/app/logger/models/trip.py b/app/logger/models/trip.py index bc807d7c..8f0163ef 100644 --- a/app/logger/models/trip.py +++ b/app/logger/models/trip.py @@ -15,6 +15,29 @@ ) +class Caver(models.Model): + """A caver that was on a trip""" + + name = models.CharField(max_length=40) + added = models.DateTimeField("caver added on", auto_now_add=True) + updated = models.DateTimeField("caver last updated", auto_now=True) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + uuid = models.UUIDField( + verbose_name="UUID", + default=uuid.uuid4, + editable=False, + unique=True, + help_text="A unique identifier for this caver.", + ) + + def __str__(self): + return self.name + + def save(self, *args, **kwargs): + self.name = self.name.strip() + super().save(*args, **kwargs) + + # noinspection PyUnresolvedReferences class Trip(models.Model): """Caving trip model.""" @@ -119,7 +142,7 @@ class Trip(models.Model): choices=TRIP_TYPES, default=SPORT, ) - cavers = models.CharField( + cavers_old = models.CharField( max_length=250, blank=True, help_text=( @@ -127,6 +150,11 @@ class Trip(models.Model): "Avoid adding yourself to this list." ), ) + cavers = models.ManyToManyField( + Caver, + blank=True, + help_text="A list of cavers that were on this trip.", + ) clubs = models.CharField( max_length=100, blank=True, diff --git a/app/templates/logger/_trip_data_blocks.html b/app/templates/logger/_trip_data_blocks.html index 2d8b68ba..f66e74b5 100644 --- a/app/templates/logger/_trip_data_blocks.html +++ b/app/templates/logger/_trip_data_blocks.html @@ -1,11 +1,11 @@ {% load users_tags %} {% load logger_tags %} -{% if trip.cavers %} +{% if trip.cavers.all %}
Cavers
- {{ trip.cavers }} + {{ trip.cavers.all|join:", " }}
{% endif %} diff --git a/app/templates/logger/profile.html b/app/templates/logger/profile.html index 966841ec..cb263afb 100644 --- a/app/templates/logger/profile.html +++ b/app/templates/logger/profile.html @@ -179,10 +179,10 @@ - {% if trip.cavers and show_cavers %} + {% if trip.cavers.all and show_cavers %} - with {{ trip.cavers }} + with {{ trip.cavers.all|join:", " }} {% endif %}