team-3/src/c3nav/mapdata/fields.py

68 lines
2.5 KiB
Python
Raw Normal View History

import json
from django.core.exceptions import ValidationError
2016-12-27 19:03:54 +01:00
from django.core.validators import RegexValidator
from django.db import models
2016-12-27 19:03:54 +01:00
from django.utils.translation import ugettext_lazy as _
from shapely import validation
2017-05-08 21:55:45 +02:00
from shapely.geometry import LineString, Polygon, mapping, shape
from shapely.geometry.base import BaseGeometry
2016-12-07 16:11:33 +01:00
from c3nav.mapdata.utils.geometry import clean_geometry
from c3nav.mapdata.utils.json import format_geojson
2016-12-28 01:55:27 +01:00
validate_bssid_lines = RegexValidator(regex=r'^([0-9a-f]{2}(:[0-9a-f]{2}){5}(\r?\n[0-9a-f]{2}(:[0-9a-f]{2}){5})*)?$',
2016-12-27 19:03:54 +01:00
message=_('please enter a newline seperated lowercase list of BSSIDs'))
def validate_geometry(geometry):
if not isinstance(geometry, BaseGeometry):
raise ValidationError('GeometryField expexted a Shapely BaseGeometry child-class.')
if not geometry.is_valid:
raise ValidationError('Invalid geometry: %s' % validation.explain_validity(geometry))
2016-09-20 16:13:47 +02:00
class GeometryField(models.TextField):
default_validators = [validate_geometry]
def __init__(self, geomtype=None, *args, **kwargs):
self.geomtype = geomtype
if geomtype not in (None, 'polygon', 'polyline'):
raise ValueError(_('GeometryField.geomtype has to be None, "polygon" or "polyline"'))
super().__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.geomtype is not None:
kwargs['geomtype'] = self.geomtype
return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return shape(json.loads(value))
def to_python(self, value):
return clean_geometry(shape(json.loads(value)))
def get_prep_value(self, value):
if self.geomtype == 'polygon' and not isinstance(value, Polygon):
raise TypeError(_('Expected Polygon instance, got %s instead.') % repr(value))
elif self.geomtype == 'polyline' and not isinstance(value, LineString):
raise TypeError(_('Expected LineString instance, got %s instead.') % repr(value))
2016-10-09 16:21:05 +02:00
return json.dumps(format_geojson(mapping(value)))
class JSONField(models.TextField):
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return json.loads(value)
def to_python(self, value):
return json.loads(value)
def get_prep_value(self, value):
return json.dumps(value)