1 from django.contrib.auth.models import User
2 from django.core.exceptions import ValidationError
3 from django.db import models
4 from django.db.models import Q
7 def __xor__(self, other):
8 return (self & (~other)) | ((~self) & other)
12 class Boulder(models.Model):
13 name = models.CharField(max_length=64)
14 difficulty = models.ForeignKey(
17 on_delete=models.PROTECT,
18 related_name='boulders',
20 mountainproject = models.URLField(null=True)
22 class BoulderDifficulty(models.Model):
23 order = models.PositiveSmallIntegerField()
24 name = models.CharField(max_length=8)
26 class Pitch(models.Model):
27 route = models.ForeignKey(
29 on_delete=models.CASCADE,
30 related_name='pitches',
32 difficulty = models.ForeignKey(
34 on_delete=models.PROTECT,
35 related_name='pitches',
38 PROTECTION_STYLE_CHOICES = (
40 ('toprope', 'Top Rope'),
44 class Route(models.Model):
45 name = models.CharField(max_length=64)
46 protection_style = models.CharField(max_length=8, choices=PROTECTION_STYLE_CHOICES)
47 mountainproject = models.URLField(null=True)
49 # TODO Write test for this
52 return self.pitches.order_by('-difficulty__order').first().difficulty
54 class RouteDifficulty(models.Model):
55 order = models.PositiveSmallIntegerField()
56 name = models.CharField(max_length=8)
58 ATTEMPT_RESULT_CHOICES = (
63 PROTECTION_CHOICES = (
71 class Attempt(models.Model):
72 user = models.ForeignKey(User, on_delete=models.CASCADE)
73 notes = models.TextField()
74 boulder = models.ForeignKey('Boulder', null=True, on_delete=models.PROTECT, related_name='attempts')
75 route = models.ForeignKey('Route', null=True, on_delete=models.PROTECT, related_name='attempts')
76 result = models.CharField(max_length=8, choices=ATTEMPT_RESULT_CHOICES)
77 prior_knowledge = models.BooleanField(default=True)
78 protection_used = models.CharField(max_length=8, choices=PROTECTION_CHOICES)
82 models.CheckConstraint(
83 check=(Q(boulder__isnull=True) ^ Q(route__isnull=True)),
84 name='attempt_boulder_xor_route',
89 ('onsight', 'On Sight'),
91 ('complete', 'Complete'),
92 ('project', 'project'),
95 class Todo(models.Model):
96 user = models.ForeignKey(User, on_delete=models.CASCADE)
97 notes = models.TextField()
98 protection = models.CharField(max_length=8, choices=PROTECTION_CHOICES)
99 boulder = models.ForeignKey('Boulder', null=True, on_delete=models.PROTECT, related_name='todos')
100 route = models.ForeignKey('Route', null=True, on_delete=models.PROTECT, related_name='todos')
104 models.CheckConstraint(
105 check=(Q(boulder__isnull=True) ^ Q(route__isnull=True)),
106 name='todo_boulder_xor_route',