diff --git a/marshmallow_mongoengine/conversion/fields.py b/marshmallow_mongoengine/conversion/fields.py index 9a641bc..dc93a76 100644 --- a/marshmallow_mongoengine/conversion/fields.py +++ b/marshmallow_mongoengine/conversion/fields.py @@ -45,7 +45,7 @@ def marshmallow_field_cls(self): class ListBuilder(MetaFieldBuilder): - AVAILABLE_PARAMS = (params.LenghtParam,) + AVAILABLE_PARAMS = (params.LengthParam,) MARSHMALLOW_FIELD_CLS = ma_fields.List def _get_marshmallow_field_cls(self): @@ -165,7 +165,7 @@ class Builder(MetaFieldBuilder): register_field(me.fields.DictField, ma_fields.Raw) register_field(me.fields.DynamicField, ma_fields.Raw) register_field(me.fields.EmailField, ma_fields.Email, - available_params=(params.LenghtParam,)) + available_params=(params.LengthParam,)) register_field(me.fields.FloatField, ma_fields.Float, available_params=(params.SizeParam,)) register_field(me.fields.GenericEmbeddedDocumentField, @@ -187,19 +187,19 @@ class Builder(MetaFieldBuilder): register_field(me.fields.ObjectIdField, ma_fields.ObjectId) register_field(me.fields.UUIDField, ma_fields.UUID) register_field(me.fields.PointField, ma_fields.Point) +register_field(me.fields.LineStringField, ma_fields.LineString) register_field(me.fields.SequenceField, ma_fields.Integer, available_params=(params.SizeParam,)) # TODO: handle value_decorator register_field(me.fields.StringField, ma_fields.String, - available_params=(params.LenghtParam, params.RegexParam)) + available_params=(params.LengthParam, params.RegexParam)) register_field(me.fields.URLField, ma_fields.URL, - available_params=(params.LenghtParam,)) + available_params=(params.LengthParam,)) register_field_builder(me.fields.EmbeddedDocumentField, EmbeddedDocumentBuilder) register_field_builder(me.fields.ListField, ListBuilder) register_field_builder(me.fields.MapField, MapBuilder) register_field_builder(me.fields.SortedListField, ListBuilder) # TODO: finish fields... # me.fields.GeoPointField: ma_fields.GeoPoint, -# me.fields.LineStringField: ma_fields.LineString, # me.fields.PolygonField: ma_fields.Polygon, # me.fields.MultiPointField: ma_fields.MultiPoint, # me.fields.MultiLineStringField: ma_fields.MultiLineString, diff --git a/marshmallow_mongoengine/conversion/params.py b/marshmallow_mongoengine/conversion/params.py index dc24dd5..8fdcea1 100644 --- a/marshmallow_mongoengine/conversion/params.py +++ b/marshmallow_mongoengine/conversion/params.py @@ -34,9 +34,9 @@ def __init__(self, field_me): self.field_kwargs['required'] = required -class LenghtParam(MetaParam): +class LengthParam(MetaParam): def __init__(self, field_me): - super(LenghtParam, self).__init__() + super(LengthParam, self).__init__() # Add a length validator for max_length/min_length maxmin_args = {} if hasattr(field_me, 'max_length'): diff --git a/marshmallow_mongoengine/fields.py b/marshmallow_mongoengine/fields.py index 96e5e2b..3ce8a66 100644 --- a/marshmallow_mongoengine/fields.py +++ b/marshmallow_mongoengine/fields.py @@ -42,6 +42,33 @@ def _serialize(self, value, attr, obj): ) +class LineString(fields.Field): + + """ + Marshmallow custom field to map with :class Mongoengine.LineStringField: + """ + + def _deserialize(self, value, attr, data): + try: + coordinates = [] + + for x, y in value['coordinates']: + coordinates.append([float(x), float(y)]) + return dict( + type='LineString', + coordinates=coordinates + ) + except Exception: + raise ValidationError('invalid value data `%s`' % value) + + def _serialize(self, value, attr, obj): + if value is None: + return missing + return dict( + coordinates=value['coordinates'] + ) + + class Reference(fields.Field): """ diff --git a/tests/test_fields.py b/tests/test_fields.py index 1785ff0..c52a107 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -409,3 +409,26 @@ class Meta: data = {'point': { 'x': '10', 'y': '20foo' }} load = DocSchema().load(data) assert 'point' in load.errors + + def test_LineStringField(self): + class Doc(me.Document): + line = me.LineStringField() + class DocSchema(ModelSchema): + class Meta: + model = Doc + doc = Doc(line={'type': 'LineString', 'coordinates': [[10, 20], [30, 40]]}) + dump = DocSchema().dump(doc) + assert not dump.errors + assert dump.data['line']['coordinates'] == [[10, 20], [30, 40]] + load = DocSchema().load(dump.data) + assert not load.errors + assert load.data.line == {'type': 'LineString', 'coordinates': [[10, 20], [30, 40]]} + # Deserialize LineString with coordinates passed as strings + data = {'line': {'coordinates': [['10', '20'], ['30', '40']]}} + load = DocSchema().load(data) + assert not load.errors + assert load.data.line == {'type': 'LineString', 'coordinates': [[10, 20], [30, 40]]} + # Try to load invalid coordinates + data = {'line': {'coordinates': [['10', '20foo']]}} + load = DocSchema().load(data) + assert 'line' in load.errors