Browse Source

Implement document filter for filtering with/without annotation

filter_fields=('seq_annotations__isnull',) is desirable but it can't.
See more detail:
https://github.com/carltongibson/django-filter/issues/743
pull/110/head
Hironsan 6 years ago
parent
commit
7a95aa9705
3 changed files with 39 additions and 3 deletions
  1. 5
      app/server/api.py
  2. 14
      app/server/filters.py
  3. 23
      app/server/tests/test_api.py

5
app/server/api.py

@ -16,6 +16,7 @@ from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser from rest_framework.parsers import MultiPartParser
from .exceptions import FileParseException from .exceptions import FileParseException
from .filters import DocumentFilter
from .models import Project, Label, Document from .models import Project, Label, Document
from .models import SequenceAnnotation from .models import SequenceAnnotation
from .permissions import IsAdminUserAndWriteOnly, IsProjectUser, IsMyEntity, IsOwnAnnotation from .permissions import IsAdminUserAndWriteOnly, IsProjectUser, IsMyEntity, IsOwnAnnotation
@ -98,8 +99,8 @@ class DocumentList(generics.ListCreateAPIView):
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
search_fields = ('text', ) search_fields = ('text', )
ordering_fields = ('created_at', 'updated_at', 'doc_annotations__updated_at', ordering_fields = ('created_at', 'updated_at', 'doc_annotations__updated_at',
'seq_annotations__updated_at')
filter_fields = ('doc_annotations__label__id', 'seq_annotations__label__id')
'seq_annotations__updated_at', 'seq2seq_annotations__updated_at')
filter_class = DocumentFilter
permission_classes = (IsAuthenticated, IsProjectUser, IsAdminUserAndWriteOnly) permission_classes = (IsAuthenticated, IsProjectUser, IsAdminUserAndWriteOnly)
def get_queryset(self): def get_queryset(self):

14
app/server/filters.py

@ -0,0 +1,14 @@
from django_filters.rest_framework import FilterSet, BooleanFilter
from .models import Document
class DocumentFilter(FilterSet):
seq_annotations__isnull = BooleanFilter(field_name='seq_annotations', lookup_expr='isnull')
doc_annotations__isnull = BooleanFilter(field_name='doc_annotations', lookup_expr='isnull')
seq2seq_annotations__isnull = BooleanFilter(field_name='seq2seq_annotations', lookup_expr='isnull')
class Meta:
model = Document
fields = ('project', 'text', 'metadata', 'created_at', 'updated_at',
'doc_annotations__label__id', 'seq_annotations__label__id',
'doc_annotations__isnull', 'seq_annotations__isnull', 'seq2seq_annotations__isnull')

23
app/server/tests/test_api.py

@ -758,11 +758,12 @@ class TestFilter(APITestCase):
cls.project_member_pass = 'project_member_pass' cls.project_member_pass = 'project_member_pass'
project_member = User.objects.create_user(username=cls.project_member_name, project_member = User.objects.create_user(username=cls.project_member_name,
password=cls.project_member_pass) password=cls.project_member_pass)
cls.main_project = mommy.make('server.TextClassificationProject', users=[project_member])
cls.main_project = mommy.make('server.SequenceLabelingProject', users=[project_member])
cls.label1 = mommy.make('server.Label', project=cls.main_project) cls.label1 = mommy.make('server.Label', project=cls.main_project)
cls.label2 = mommy.make('server.Label', project=cls.main_project) cls.label2 = mommy.make('server.Label', project=cls.main_project)
doc1 = mommy.make('server.Document', project=cls.main_project) doc1 = mommy.make('server.Document', project=cls.main_project)
doc2 = mommy.make('server.Document', project=cls.main_project) doc2 = mommy.make('server.Document', project=cls.main_project)
doc3 = mommy.make('server.Document', project=cls.main_project)
mommy.make('server.SequenceAnnotation', document=doc1, user=project_member, label=cls.label1) mommy.make('server.SequenceAnnotation', document=doc1, user=project_member, label=cls.label1)
mommy.make('server.SequenceAnnotation', document=doc2, user=project_member, label=cls.label2) mommy.make('server.SequenceAnnotation', document=doc2, user=project_member, label=cls.label2)
cls.url = reverse(viewname='doc_list', args=[cls.main_project.id]) cls.url = reverse(viewname='doc_list', args=[cls.main_project.id])
@ -777,6 +778,26 @@ class TestFilter(APITestCase):
for d1, d2 in zip(response.data['results'], docs): for d1, d2 in zip(response.data['results'], docs):
self.assertEqual(d1['id'], d2['id']) self.assertEqual(d1['id'], d2['id'])
def test_can_filter_doc_with_annotation(self):
params = {'seq_annotations__isnull': False}
self.client.login(username=self.project_member_name,
password=self.project_member_pass)
response = self.client.get(self.url, format='json', data=params)
docs = Document.objects.filter(project=self.main_project, seq_annotations__isnull=False).values()
self.assertEqual(response.data['count'], docs.count())
for d1, d2 in zip(response.data['results'], docs):
self.assertEqual(d1['id'], d2['id'])
def test_can_filter_doc_without_anotation(self):
params = {'seq_annotations__isnull': True}
self.client.login(username=self.project_member_name,
password=self.project_member_pass)
response = self.client.get(self.url, format='json', data=params)
docs = Document.objects.filter(project=self.main_project, seq_annotations__isnull=True).values()
self.assertEqual(response.data['count'], docs.count())
for d1, d2 in zip(response.data['results'], docs):
self.assertEqual(d1['id'], d2['id'])
class TestUploader(APITestCase): class TestUploader(APITestCase):

Loading…
Cancel
Save