Implement item update and deletion.
Deletion is essentially an update with "isDeletion" set to True.
This commit is contained in:
parent
727cd3e5fa
commit
4054a2f78c
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.3 on 2020-02-26 13:17
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('django_etesync', '0012_auto_20200220_2038'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='collectionitemrevision',
|
||||||
|
name='is_deletion',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
18
django_etesync/migrations/0014_auto_20200226_1322.py
Normal file
18
django_etesync/migrations/0014_auto_20200226_1322.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.3 on 2020-02-26 13:22
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('django_etesync', '0013_collectionitemrevision_is_deletion'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='collectionitemrevision',
|
||||||
|
old_name='is_deletion',
|
||||||
|
new_name='isDeletion',
|
||||||
|
),
|
||||||
|
]
|
18
django_etesync/migrations/0015_auto_20200226_1349.py
Normal file
18
django_etesync/migrations/0015_auto_20200226_1349.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.3 on 2020-02-26 13:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('django_etesync', '0014_auto_20200226_1322'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='collectionitemrevision',
|
||||||
|
name='current',
|
||||||
|
field=models.BooleanField(blank=True, db_index=True, default=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
@ -80,7 +80,8 @@ class CollectionItemRevision(models.Model):
|
|||||||
item = models.ForeignKey(CollectionItem, related_name='revisions', on_delete=models.CASCADE)
|
item = models.ForeignKey(CollectionItem, related_name='revisions', on_delete=models.CASCADE)
|
||||||
chunks = models.ManyToManyField(CollectionItemChunk, related_name='items')
|
chunks = models.ManyToManyField(CollectionItemChunk, related_name='items')
|
||||||
hmac = models.CharField(max_length=50, blank=False, null=False)
|
hmac = models.CharField(max_length=50, blank=False, null=False)
|
||||||
current = models.BooleanField(db_index=True, default=True)
|
current = models.BooleanField(db_index=True, default=True, blank=True, null=True)
|
||||||
|
isDeletion = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('item', 'current')
|
unique_together = ('item', 'current')
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import base64
|
import base64
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db import transaction
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ class CollectionItemRevisionBaseSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.CollectionItemRevision
|
model = models.CollectionItemRevision
|
||||||
fields = ('version', 'encryptionKey', 'chunks', 'hmac')
|
fields = ('version', 'encryptionKey', 'chunks', 'hmac', 'isDeletion')
|
||||||
|
|
||||||
|
|
||||||
class CollectionItemRevisionSerializer(CollectionItemRevisionBaseSerializer):
|
class CollectionItemRevisionSerializer(CollectionItemRevisionBaseSerializer):
|
||||||
@ -111,12 +112,29 @@ class CollectionItemRevisionInlineSerializer(CollectionItemRevisionBaseSerialize
|
|||||||
|
|
||||||
|
|
||||||
class CollectionItemSerializer(serializers.ModelSerializer):
|
class CollectionItemSerializer(serializers.ModelSerializer):
|
||||||
content = CollectionItemRevisionSerializer(read_only=True, many=False)
|
content = CollectionItemRevisionSerializer(many=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.CollectionItem
|
model = models.CollectionItem
|
||||||
fields = ('uid', 'content')
|
fields = ('uid', 'content')
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
"""Function that's called when this serializer is meant to update an item"""
|
||||||
|
revision_data = validated_data.pop('content')
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
chunks = revision_data.pop('chunks')
|
||||||
|
revision = models.CollectionItemRevision.objects.create(**revision_data, item=instance)
|
||||||
|
revision.chunks.set(chunks)
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class CollectionItemInlineSerializer(CollectionItemSerializer):
|
class CollectionItemInlineSerializer(CollectionItemSerializer):
|
||||||
content = CollectionItemRevisionInlineSerializer(read_only=True, many=False)
|
content = CollectionItemRevisionInlineSerializer(read_only=True, many=False)
|
||||||
|
@ -90,7 +90,7 @@ class CollectionViewSet(BaseViewSet):
|
|||||||
|
|
||||||
|
|
||||||
class CollectionItemViewSet(BaseViewSet):
|
class CollectionItemViewSet(BaseViewSet):
|
||||||
allowed_methods = ['GET', 'POST']
|
allowed_methods = ['GET', 'POST', 'PUT']
|
||||||
permission_classes = BaseViewSet.permission_classes
|
permission_classes = BaseViewSet.permission_classes
|
||||||
queryset = CollectionItem.objects.all()
|
queryset = CollectionItem.objects.all()
|
||||||
serializer_class = CollectionItemSerializer
|
serializer_class = CollectionItemSerializer
|
||||||
@ -133,11 +133,7 @@ class CollectionItemViewSet(BaseViewSet):
|
|||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
def destroy(self, request, collection_uid=None, uid=None):
|
def destroy(self, request, collection_uid=None, uid=None):
|
||||||
# FIXME: implement
|
# 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)
|
|
||||||
|
|
||||||
def 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 partial_update(self, request, collection_uid=None, uid=None):
|
def partial_update(self, request, collection_uid=None, uid=None):
|
||||||
|
Loading…
Reference in New Issue
Block a user