Collections: use the member stokens for filtering based on stoken
While at it, also generalised the stoken handling to be generic and extendible.
This commit is contained in:
parent
1f18f4e50b
commit
d93a5d3f06
@ -17,6 +17,7 @@ from pathlib import Path
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db.models import Q
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.crypto import get_random_string
|
||||
|
||||
@ -51,12 +52,14 @@ class Collection(models.Model):
|
||||
|
||||
@cached_property
|
||||
def stoken(self):
|
||||
last_revision = CollectionItemRevision.objects.filter(item__collection=self).last()
|
||||
if last_revision is None:
|
||||
# FIXME: what is the etag for None? Though if we use the revision for collection it should be shared anyway.
|
||||
return None
|
||||
stoken = Stoken.objects.filter(
|
||||
Q(collectionitemrevision__item__collection=self) | Q(collectionmember__collection=self)
|
||||
).order_by('id').last()
|
||||
|
||||
return last_revision.stoken.uid
|
||||
if stoken is None:
|
||||
raise Exception('stoken is None. Should never happen')
|
||||
|
||||
return stoken.uid
|
||||
|
||||
|
||||
class CollectionItem(models.Model):
|
||||
|
@ -13,12 +13,14 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
from functools import reduce
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import transaction, IntegrityError
|
||||
from django.db.models import Max
|
||||
from django.db.models import Max, Q
|
||||
from django.db.models.functions import Greatest
|
||||
from django.http import HttpResponseBadRequest, HttpResponse, Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
@ -70,7 +72,7 @@ User = get_user_model()
|
||||
class BaseViewSet(viewsets.ModelViewSet):
|
||||
authentication_classes = tuple(app_settings.API_AUTHENTICATORS)
|
||||
permission_classes = tuple(app_settings.API_PERMISSIONS)
|
||||
stoken_id_field = None
|
||||
stoken_id_fields = None
|
||||
|
||||
def get_serializer_class(self):
|
||||
serializer_class = self.serializer_class
|
||||
@ -93,20 +95,19 @@ class BaseViewSet(viewsets.ModelViewSet):
|
||||
return None
|
||||
|
||||
def filter_by_stoken(self, request, queryset):
|
||||
stoken_id_field = self.stoken_id_field + '__id'
|
||||
|
||||
stoken_rev = self.get_stoken_obj(request)
|
||||
if stoken_rev is not None:
|
||||
filter_by = {stoken_id_field + '__gt': stoken_rev.id}
|
||||
queryset = queryset.filter(**filter_by)
|
||||
filter_by_map = map(lambda x: Q(**{x + '__gt': stoken_rev.id}), self.stoken_id_fields)
|
||||
filter_by = reduce(lambda x, y: x | y, filter_by_map)
|
||||
queryset = queryset.filter(filter_by).distinct()
|
||||
|
||||
return queryset, stoken_rev
|
||||
|
||||
def get_queryset_stoken(self, queryset):
|
||||
stoken_id_field = self.stoken_id_field + '__id'
|
||||
|
||||
new_stoken_id = queryset.aggregate(stoken_id=Max(stoken_id_field))['stoken_id']
|
||||
new_stoken = new_stoken_id and Stoken.objects.get(id=new_stoken_id).uid
|
||||
aggr_fields = {x: Max(x) for x in self.stoken_id_fields}
|
||||
aggr = queryset.aggregate(**aggr_fields)
|
||||
maxid = max(map(lambda x: x or -1, aggr.values()))
|
||||
new_stoken = (maxid >= 0) and Stoken.objects.get(id=maxid).uid
|
||||
|
||||
return queryset, new_stoken
|
||||
|
||||
@ -129,7 +130,7 @@ class CollectionViewSet(BaseViewSet):
|
||||
queryset = Collection.objects.all()
|
||||
serializer_class = CollectionSerializer
|
||||
lookup_field = 'uid'
|
||||
stoken_id_field = 'items__revisions__stoken'
|
||||
stoken_id_fields = ['items__revisions__stoken__id', 'members__stoken__id']
|
||||
|
||||
def get_queryset(self, queryset=None):
|
||||
if queryset is None:
|
||||
@ -189,7 +190,7 @@ class CollectionItemViewSet(BaseViewSet):
|
||||
queryset = CollectionItem.objects.all()
|
||||
serializer_class = CollectionItemSerializer
|
||||
lookup_field = 'uid'
|
||||
stoken_id_field = 'revisions__stoken'
|
||||
stoken_id_fields = ['revisions__stoken__id']
|
||||
|
||||
def get_queryset(self):
|
||||
collection_uid = self.kwargs['collection_uid']
|
||||
|
Loading…
Reference in New Issue
Block a user