| 1 | class _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 |
|
|---|
| 33 | def _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 |
|
|---|
| 40 | def _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 |
|
|---|
| 48 | class 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)
|
|---|