CollectionItem: implement both update and create.

master
Tom Hacohen 5 years ago
parent 23dcbc1f9e
commit 4c7e30eca5

@ -123,36 +123,31 @@ class CollectionItemSerializer(serializers.ModelSerializer):
"""Function that's called when this serializer creates an item""" """Function that's called when this serializer creates an item"""
stoken = validated_data.pop('stoken') stoken = validated_data.pop('stoken')
revision_data = validated_data.pop('content') revision_data = validated_data.pop('content')
instance = self.__class__.Meta.model(**validated_data) uid = validated_data.pop('uid')
Model = self.__class__.Meta.model
with transaction.atomic(): with transaction.atomic():
if stoken is not None: instance, created = Model.objects.get_or_create(uid=uid, defaults=validated_data)
raise serializers.ValidationError('Stoken is not None') cur_stoken = instance.stoken if not created else None
instance.save() if cur_stoken != stoken:
raise serializers.ValidationError('Wrong stoken. Expected {} got {}'.format(cur_stoken, stoken))
if not created:
# We don't have to use select_for_update here because the unique constraint on current guards against
# the race condition. But it's a good idea because it'll lock and wait rather than fail.
current_revision = instance.revisions.filter(current=True).select_for_update().first()
current_revision.current = None
current_revision.save()
process_revisions_for_item(instance, revision_data) process_revisions_for_item(instance, revision_data)
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
"""Function that's called when this serializer is meant to update an item""" # We never update, we always update in the create method
stoken = validated_data.pop('stoken') raise NotImplementedError()
revision_data = validated_data.pop('content')
with transaction.atomic():
if stoken != instance.stoken:
raise serializers.ValidationError('Wrong stoken. Expected {} got {}'.format(instance.stoken, stoken))
# We don't have to use select_for_update here because the unique constraint on current guards against
# the race condition. But it's a good idea because it'll lock and wait rather than fail.
current_revision = instance.revisions.filter(current=True).select_for_update().first()
current_revision.current = None
current_revision.save()
process_revisions_for_item(instance, revision_data)
return instance
class CollectionItemDepSerializer(serializers.ModelSerializer): class CollectionItemDepSerializer(serializers.ModelSerializer):

@ -187,8 +187,10 @@ class CollectionItemViewSet(BaseViewSet):
# We can't have destroy because we need to get data from the user (in the body) such as hmac. # We can't have destroy because we need to get data from the user (in the body) such as hmac.
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def update(self, request, collection_uid=None, uid=None):
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def partial_update(self, request, collection_uid=None, uid=None): def partial_update(self, request, collection_uid=None, uid=None):
# FIXME: implement, or should it be implemented elsewhere?
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def list(self, request, collection_uid=None): def list(self, request, collection_uid=None):

Loading…
Cancel
Save