diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0c0da84e..9898df05 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,7 +5,9 @@ ChangeLog master (unreleased) =================== -- Nothing here yet +* Enforce unicity of keys in NestedListSerializers (#202) +* Define __unicode__ and __str__ on models (#200) +* Fix regression on presets_lists endpoint (#199) Release 0.8.1 (2017-03-07) ========================== diff --git a/demo/tests/tests_integration.py b/demo/tests/tests_integration.py index 265e3642..d4ad5690 100644 --- a/demo/tests/tests_integration.py +++ b/demo/tests/tests_integration.py @@ -86,6 +86,15 @@ def test_simple(self): field.accesses.filter(access_id=access, level=level).exists() ) + def test_fields_slug(self): + data = deepcopy(form_data) + # duplicate field + data['fields'] *= 2 + res = self.client.post( + reverse('formidable:form_create'), data, format='json' + ) + self.assertEquals(res.status_code, 400) + def test_with_items_in_fields(self): initial_count = Formidable.objects.count() res = self.client.post( @@ -179,6 +188,17 @@ def test_create_field_on_update(self): self.assertEquals(form.pk, self.form.pk) self.assertEquals(form.fields.count(), 2) + def test_duplicate_items_update(self): + # create a form with items + data = deepcopy(form_data_items) + res = self.client.put(self.edit_url, data, format='json') + self.assertEquals(res.status_code, 200) + # update items with duplicate entries + data['fields'] *= 2 + res = self.client.put(self.edit_url, data, format='json') + # expect validation error + self.assertEquals(res.status_code, 400) + def test_delete_field_on_update(self): self.form.fields.create( type_id='text', slug='textslug', label='mytext', diff --git a/formidable/serializers/access.py b/formidable/serializers/access.py index 91a0ebda..eac1a4c4 100644 --- a/formidable/serializers/access.py +++ b/formidable/serializers/access.py @@ -36,6 +36,7 @@ class AccessListSerializer(NestedListSerializer): parent_name = 'field_id' def validate(self, data): + data = super(AccessListSerializer, self).validate(data) accesses_id = [accesses['access_id'] for accesses in data] for access in get_accesses(): diff --git a/formidable/serializers/fields.py b/formidable/serializers/fields.py index 1bef7754..8feaa804 100644 --- a/formidable/serializers/fields.py +++ b/formidable/serializers/fields.py @@ -41,6 +41,8 @@ def validate(self, validated_data): order before the update/create method sorts the validated data by id. """ + validated_data = super(FieldListSerializer, self).validate( + validated_data) for index, data in enumerate(validated_data): data['order'] = index diff --git a/formidable/serializers/list.py b/formidable/serializers/list.py index c52758a4..91e10e1d 100644 --- a/formidable/serializers/list.py +++ b/formidable/serializers/list.py @@ -4,6 +4,7 @@ import logging +from rest_framework.exceptions import ValidationError from rest_framework.serializers import ListSerializer logger = logging.getLogger(__name__) @@ -50,6 +51,21 @@ def _extract_id(self, qs, validated_data): deleted_ids = db_ids - validated_ids return created_ids, updated_ids, deleted_ids + def validate(self, data): + """ + ensure that field_id is unique among children + """ + data = super(NestedListSerializer, self).validate(data) + + if self.field_id: + if len(data) != len(set(f[self.field_id] for f in data)): + msg = 'The fields {field_id} must make a unique set.'.format( + field_id=self.field_id + ) + raise ValidationError(msg, code='unique') + + return data + class NestedListSerializerDummyUpdate(NestedListSerializer):