From: David Kerkeslager Date: Fri, 26 Feb 2021 01:04:23 +0000 (-0500) Subject: Add admin interface and fix some model issues X-Git-Url: https://code.kerkeslager.com/?p=tickle;a=commitdiff_plain;h=7f29febb2627d482ff9ed9f29392c2fe64be32a7 Add admin interface and fix some model issues --- diff --git a/tickle/admin.py b/tickle/admin.py index 8c38f3f..4484351 100644 --- a/tickle/admin.py +++ b/tickle/admin.py @@ -1,3 +1,19 @@ from django.contrib import admin -# Register your models here. +from . import models + +class PitchInline(admin.TabularInline): + model = models.Pitch + +class RouteAdmin(admin.ModelAdmin): + inlines = ( + PitchInline, + ) + +admin.site.register(models.Route, RouteAdmin) + +admin.site.register(models.Attempt) +admin.site.register(models.Boulder) +admin.site.register(models.BoulderDifficulty) +admin.site.register(models.RouteDifficulty) +admin.site.register(models.Todo) diff --git a/tickle/migrations/0001_initial.py b/tickle/migrations/0001_initial.py index 7955d21..1e8635c 100644 --- a/tickle/migrations/0001_initial.py +++ b/tickle/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.7 on 2021-02-25 19:26 +# Generated by Django 3.1.7 on 2021-02-25 19:46 from django.conf import settings from django.db import migrations, models @@ -53,6 +53,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('notes', models.TextField()), ('protection', models.CharField(choices=[('none', 'None'), ('bolts', 'Bolts'), ('gear', 'Gear'), ('pad', 'Pad'), ('tr', 'Top Rope')], max_length=8)), + ('style', models.CharField(choices=[('onsight', 'On Sight'), ('flash', 'Flash'), ('project', 'Project'), ('other', 'Other')], max_length=8)), ('boulder', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='todos', to='tickle.boulder')), ('route', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='todos', to='tickle.route')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), @@ -62,6 +63,7 @@ class Migration(migrations.Migration): name='Pitch', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.PositiveSmallIntegerField()), ('difficulty', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='pitches', to='tickle.routedifficulty')), ('route', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pitches', to='tickle.route')), ], @@ -75,6 +77,7 @@ class Migration(migrations.Migration): name='Attempt', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField()), ('notes', models.TextField()), ('result', models.CharField(choices=[('send', 'Sent'), ('fall', 'Fall')], max_length=8)), ('prior_knowledge', models.BooleanField(default=True)), diff --git a/tickle/migrations/0002_auto_20210225_1949.py b/tickle/migrations/0002_auto_20210225_1949.py new file mode 100644 index 0000000..1b487b9 --- /dev/null +++ b/tickle/migrations/0002_auto_20210225_1949.py @@ -0,0 +1,25 @@ +# Generated by Django 3.1.7 on 2021-02-25 19:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickle', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='boulder', + name='mountainproject', + field=models.URLField(blank=True, default=''), + preserve_default=False, + ), + migrations.AlterField( + model_name='route', + name='mountainproject', + field=models.URLField(blank=True, default=''), + preserve_default=False, + ), + ] diff --git a/tickle/models.py b/tickle/models.py index 268d7b0..176a4a5 100644 --- a/tickle/models.py +++ b/tickle/models.py @@ -17,13 +17,23 @@ class Boulder(models.Model): on_delete=models.PROTECT, related_name='boulders', ) - mountainproject = models.URLField(null=True) + mountainproject = models.URLField(blank=True) + + def __str__(self): + return '{} ({})'.format(self.name, self.difficulty) class BoulderDifficulty(models.Model): order = models.PositiveSmallIntegerField() name = models.CharField(max_length=8) + class Meta: + ordering = ('order',) + + def __str__(self): + return self.name + class Pitch(models.Model): + order = models.PositiveSmallIntegerField() route = models.ForeignKey( 'Route', on_delete=models.CASCADE, @@ -35,6 +45,12 @@ class Pitch(models.Model): related_name='pitches', ) + class Meta: + ordering = ('order',) + + def __str__(self): + return 'P{} ({})'.format(self.order, self.difficulty) + PROTECTION_STYLE_CHOICES = ( ('sport', 'Sport'), ('toprope', 'Top Rope'), @@ -44,17 +60,23 @@ PROTECTION_STYLE_CHOICES = ( class Route(models.Model): name = models.CharField(max_length=64) protection_style = models.CharField(max_length=8, choices=PROTECTION_STYLE_CHOICES) - mountainproject = models.URLField(null=True) + mountainproject = models.URLField(blank=True) # TODO Write test for this @property def difficulty(self): return self.pitches.order_by('-difficulty__order').first().difficulty + def __str__(self): + return '{} ({})'.format(self.name, self.difficulty) + class RouteDifficulty(models.Model): order = models.PositiveSmallIntegerField() name = models.CharField(max_length=8) + def __str__(self): + return self.name + ATTEMPT_RESULT_CHOICES = ( ('send', 'Sent'), ('fall', 'Fall'), @@ -70,6 +92,7 @@ PROTECTION_CHOICES = ( class Attempt(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) + date = models.DateField() notes = models.TextField() boulder = models.ForeignKey('Boulder', null=True, on_delete=models.PROTECT, related_name='attempts') route = models.ForeignKey('Route', null=True, on_delete=models.PROTECT, related_name='attempts') @@ -85,11 +108,13 @@ class Attempt(models.Model): ), ) + ordering = ('date',) + STYLE_CHOICES = ( ('onsight', 'On Sight'), ('flash', 'Flash'), - ('complete', 'Complete'), - ('project', 'project'), + ('project', 'Project'), + ('other', 'Other'), ) class Todo(models.Model): @@ -98,6 +123,7 @@ class Todo(models.Model): protection = models.CharField(max_length=8, choices=PROTECTION_CHOICES) boulder = models.ForeignKey('Boulder', null=True, on_delete=models.PROTECT, related_name='todos') route = models.ForeignKey('Route', null=True, on_delete=models.PROTECT, related_name='todos') + style = models.CharField(max_length=8, choices=STYLE_CHOICES) class Meta: constraints = ( @@ -106,3 +132,15 @@ class Todo(models.Model): name='todo_boulder_xor_route', ), ) + + ordering = ('route__name',) + + def __str__(self): + if self.boulder: + climb = self.boulder + elif self.route: + climb = self.route + else: + raise Exception() + + return '{} {}'.format(self.style, climb)