Ticket #16986: model_clean_mixin.py

File model_clean_mixin.py, 2.3 KB (added by David Foster, 13 years ago)
Line 
1class _ModelCleanWorkaroundMixin(object):
2 """
3 Mixin for Model subclasses that wish to raise ValidationErrors
4 in Model.clean() that target individual fields. As of Django 2.3
5 this is not possible, due to <https://code.djangoproject.com/ticket/16986>.
6 """
7
8 # Workaround for: https://code.djangoproject.com/ticket/16986
9 def clean_fields(self, **kwargs):
10 try:
11 super(_ModelCleanWorkaroundMixin, self).clean_fields(**kwargs)
12 except ValidationError as e1:
13 if not hasattr(e1, 'message_dict'):
14 e1.message_dict = {NON_FIELD_ERRORS: e1.messages}
15 else:
16 e1 = None
17
18 try:
19 # If not for this workaround, this method would be called clean()
20 self.clean_self()
21 except ValidationError as e2:
22 pass
23 else:
24 e2 = None
25
26 if e1 and e2:
27 raise ValidationError(dict(e1.message_dict, **e2.message_dict))
28 elif e1 and not e2:
29 raise e1
30 elif not e1 and e2:
31 raise e2
32
33def _createLatitudeField():
34 return models.DecimalField(max_digits=8, decimal_places=6,
35 validators=[
36 validators.MinValueValidator(Decimal('-90.000000')),
37 validators.MaxValueValidator(Decimal('90.000000')),
38 ])
39
40def _createLongitudeField():
41 return models.DecimalField(max_digits=9, decimal_places=6,
42 validators=[
43 validators.MinValueValidator(Decimal('-180.000000')),
44 validators.MaxValueValidator(Decimal('180.000000')),
45 ])
46
47
48class Region(_ModelCleanWorkaroundMixin, models.Model):
49 south = _createLatitudeField()
50 west = _createLongitudeField()
51 north = _createLatitudeField()
52 east = _createLongitudeField()
53
54 def clean_self(self):
55 message_dict = defaultdict(list)
56
57 if self.west and self.east and (not self.west <= self.east):
58 message_dict['south'].append('Southwest pin must be west of the northeast pin.')
59 if self.south and self.north and (not self.south <= self.north):
60 message_dict['south'].append('Southwest pin must be south of the northeast pin.')
61
62 if len(message_dict):
63 raise ValidationError(message_dict)
Back to Top