diff --git a/delft3dworker/fixtures/default_template.json b/delft3dworker/fixtures/default_template.json
index f23354c0..36298cae 100644
--- a/delft3dworker/fixtures/default_template.json
+++ b/delft3dworker/fixtures/default_template.json
@@ -100,14 +100,14 @@
{
"name": "Base level change",
"validators": {
- "max": 3.0,
- "min": -3.0
+ "max": 80,
+ "min": -80
},
"factor": true,
- "units": "m",
+ "units": "%",
"type": "numeric",
"id": "baselevel",
- "description": "Positive values define 'a base level rise', negative values define 'a base level fall'. The magnitude of this value should be based on simulation stop time: the larger the stop time value, the larger the magnitude of this value can be."
+ "description": "Positive values define 'a base level rise', negative values define 'a base level fall'."
}
],
"name": "Forcing"
@@ -285,15 +285,15 @@
"name": "Base level change",
"default": 0,
"validators": {
- "max": 3.0,
+ "max": 80.0,
"required": true,
- "min": -3.0
+ "min": -80.0
},
"factor": true,
- "units": "m",
+ "units": "%",
"type": "numeric",
"id": "baselevel",
- "description": "Positive values define 'a base level rise', negative values define 'a base level fall'. The magnitude of this value should be based on simulation stop time: the larger the stop time value, the larger the magnitude of this value can be."
+ "description": "This is a percentage of the level change produced by the basin slope.
Click on the button below to see a table with the absolute values."
}
],
"name": "Forcing"
@@ -346,4 +346,4 @@
"model": "delft3dworker.template",
"pk": 53
}
-]
+]
\ No newline at end of file
diff --git a/delft3dworker/models.py b/delft3dworker/models.py
index 3ab196d0..16e85f60 100644
--- a/delft3dworker/models.py
+++ b/delft3dworker/models.py
@@ -1667,14 +1667,18 @@ class Template(models.Model):
meta = JSONField(blank=True)
sections = JSONField(blank=True)
- def save(self, *args, **kwargs):
- returnval = super(Template, self).save(*args, **kwargs)
+ # The following method is disabled as it adds to much garbage
+ # to the MAIN search template
+ # TODO: implement proper search template which uses REST list_views
+
+ # def save(self, *args, **kwargs):
+ # returnval = super(Template, self).save(*args, **kwargs)
- # update the MAIN search form after any template save
- searchform, created = SearchForm.objects.get_or_create(name="MAIN")
- searchform.update()
+ # # update the MAIN search form after any template save
+ # searchform, created = SearchForm.objects.get_or_create(name="MAIN")
+ # searchform.update()
- return returnval
+ # return returnval
def __unicode__(self):
return self.name
diff --git a/delft3dworker/test_models.py b/delft3dworker/test_models.py
index 37c03093..328cd971 100644
--- a/delft3dworker/test_models.py
+++ b/delft3dworker/test_models.py
@@ -1474,38 +1474,40 @@ def setUp(self):
]
""")
- def test_search_form_builds_on_template_save(self):
- """
- Test if saving multiple templates creates and updates the search form.
- """
-
- template = Template.objects.create(
- name='Template 1',
- meta='{}',
- sections=self.sections_a,
- )
-
- # first template created non-existing search form
- searchforms = SearchForm.objects.filter(name='MAIN')
- self.assertEqual(len(searchforms), 1)
-
- template2 = Template.objects.create(
- name='Template 2',
- meta='{}',
- sections=self.sections_b,
- )
-
- # second template did not create an additional search form
- searchforms = SearchForm.objects.filter(name='MAIN')
- self.assertEqual(len(searchforms), 1)
-
- # all fields are as expected
- searchform = searchforms[0]
- self.assertEqual(
- searchform.templates,
- self.templates_res
- )
- self.assertEqual(
- searchform.sections,
- self.sections_res
- )
+ # TODO: implement proper means to generate search form json
+
+ # def test_search_form_builds_on_template_save(self):
+ # """
+ # Test if saving multiple templates creates and updates the search form.
+ # """
+
+ # template = Template.objects.create(
+ # name='Template 1',
+ # meta='{}',
+ # sections=self.sections_a,
+ # )
+
+ # # first template created non-existing search form
+ # searchforms = SearchForm.objects.filter(name='MAIN')
+ # self.assertEqual(len(searchforms), 1)
+
+ # template2 = Template.objects.create(
+ # name='Template 2',
+ # meta='{}',
+ # sections=self.sections_b,
+ # )
+
+ # # second template did not create an additional search form
+ # searchforms = SearchForm.objects.filter(name='MAIN')
+ # self.assertEqual(len(searchforms), 1)
+
+ # # all fields are as expected
+ # searchform = searchforms[0]
+ # self.assertEqual(
+ # searchform.templates,
+ # self.templates_res
+ # )
+ # self.assertEqual(
+ # searchform.sections,
+ # self.sections_res
+ # )
diff --git a/delft3dworker/test_views.py b/delft3dworker/test_views.py
index da835e89..b05cc729 100644
--- a/delft3dworker/test_views.py
+++ b/delft3dworker/test_views.py
@@ -19,6 +19,7 @@
from mock import MagicMock
from mock import patch
+from delft3dworker.models import Container
from delft3dworker.models import Scenario
from delft3dworker.models import Scene
from delft3dworker.models import Template
@@ -524,6 +525,10 @@ def setUp(self):
}
}
self.scene_1.save()
+ container_1 = Container.objects.create(
+ version={'d3d': 1},
+ scene=self.scene_1
+ )
self.scene_2 = Scene.objects.create(
name='Testscene 2',
@@ -544,6 +549,10 @@ def setUp(self):
}
}
self.scene_2.save()
+ container_2 = Container.objects.create(
+ version={'d3d': 2, 'other': 'a'},
+ scene=self.scene_2
+ )
# Object general
assign_perm('view_scenario', self.user_bar, self.scenario)
@@ -713,6 +722,38 @@ def test_search_hack(self):
query = {'parameter': "hack,mud,grease,more"}
self.assertEqual(len(self._request(query)), 2)
+ def test_search_versions(self):
+ """
+ Test search options
+ """
+
+ query = {'versions': "argh"}
+ self.assertEqual(len(self._request(query)), 2)
+
+ query = {'versions': "{}"}
+ self.assertEqual(len(self._request(query)), 2)
+
+ query = {'versions': '{"d3d":[1]}'}
+ self.assertEqual(len(self._request(query)), 1)
+
+ query = {'versions': '{"d3d":[2]}'}
+ self.assertEqual(len(self._request(query)), 1)
+
+ query = {'versions': '{"d3d":[1,2]}'}
+ self.assertEqual(len(self._request(query)), 2)
+
+ query = {'versions': '{"d3d":[1,2], "other": "a"}'}
+ self.assertEqual(len(self._request(query)), 2)
+
+ query = {'versions': '{"d3d":[1], "other": "a"}'}
+ self.assertEqual(len(self._request(query)), 2)
+
+ query = {'versions': '{"d3d":[2], "other": "a"}'}
+ self.assertEqual(len(self._request(query)), 1)
+
+ query = {'versions': '{"d3d":None}'}
+ self.assertEqual(len(self._request(query)), 2)
+
def _request(self, query):
url = reverse('scene-list')
self.client.login(username='bar', password='secret')
@@ -720,6 +761,113 @@ def _request(self, query):
return response.data
+class SceneVersionTestCase(APITestCase):
+ """
+ SceneVersionTestCase
+ Tests the Scenario Django REST API
+ """
+
+ def setUp(self):
+ user_bar = User.objects.create_user(
+ username='bar',
+ password='secret'
+ )
+ scenario = Scenario.objects.create(
+ name='Testscenario',
+ owner=user_bar,
+ )
+
+ scene_1 = Scene.objects.create(
+ name='Testscene 1',
+ owner=user_bar
+ )
+ scene_1.scenario.add(scenario)
+
+ scene_2 = Scene.objects.create(
+ name='Testscene 1',
+ owner=user_bar
+ )
+ scene_2.scenario.add(scenario)
+ container_2_1 = Container.objects.create(
+ version={ 'd3dversion': '1' },
+ scene=scene_2
+ )
+
+ scene_3 = Scene.objects.create(
+ name='Testscene 1',
+ owner=user_bar
+ )
+ scene_3.scenario.add(scenario)
+ container_3_1 = Container.objects.create(
+ version={ 'd3dversion': '2' },
+ scene=scene_3
+ )
+
+ scene_4 = Scene.objects.create(
+ name='Testscene 1',
+ owner=user_bar
+ )
+ scene_4.scenario.add(scenario)
+ container_4_1 = Container.objects.create(
+ version={ 'd3dversion': '1' },
+ scene=scene_4
+ )
+ container_4_2 = Container.objects.create(
+ version={ 'svnversion': 'a' },
+ scene=scene_4
+ )
+
+ scene_5 = Scene.objects.create(
+ name='Testscene 1',
+ owner=user_bar
+ )
+ scene_5.scenario.add(scenario)
+ container_5_1 = Container.objects.create(
+ version={ 'd3dversion': '1' },
+ scene=scene_5
+ )
+ container_5_2 = Container.objects.create(
+ version={ 'svnversion': 'b' },
+ scene=scene_5
+ )
+ container_5_3 = Container.objects.create(
+ version={ 'anything': 'I' },
+ scene=scene_5
+ )
+
+ # Object general
+ assign_perm('view_scenario', user_bar, scenario)
+ assign_perm('view_scene', user_bar, scene_1)
+ assign_perm('view_scene', user_bar, scene_2)
+ assign_perm('view_scene', user_bar, scene_3)
+ assign_perm('view_scene', user_bar, scene_4)
+ assign_perm('view_scene', user_bar, scene_5)
+
+ # Model general
+ user_bar.user_permissions.add(
+ Permission.objects.get(codename='view_scenario'))
+ user_bar.user_permissions.add(
+ Permission.objects.get(codename='view_scene'))
+
+ # Refetch to empty permissions cache
+ user_bar = User.objects.get(pk=user_bar.pk)
+
+ def test_get_versions(self):
+ # detail view
+ url = reverse('scene-versions')
+
+ # foo can see
+ self.client.login(username='bar', password='secret')
+ response = self.client.get(url, format='json')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response.render()
+ self.assertEqual(response.data, {
+ 'svnversion': set(['a', 'b']),
+ 'd3dversion': set(['1', '2']),
+ 'anything': set(['I'])
+ })
+
+
class ScenarioTestCase(APITestCase):
"""
ScenarioTestCase
diff --git a/delft3dworker/views.py b/delft3dworker/views.py
index 9dee17cb..8049bbff 100644
--- a/delft3dworker/views.py
+++ b/delft3dworker/views.py
@@ -6,12 +6,14 @@
import datetime
import django_filters
import io
+import json
import logging
import zipfile
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse_lazy
+from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.dateparse import parse_date
@@ -33,6 +35,7 @@
from rest_framework.decorators import list_route
from rest_framework.response import Response
+from delft3dworker.models import Container
from delft3dworker.models import Scenario
from delft3dworker.models import Scene
from delft3dworker.models import Template
@@ -225,6 +228,8 @@ def get_queryset(self):
shared = self.request.query_params.getlist('shared', [])
users = self.request.query_params.getlist('users', [])
+ versions = self.request.query_params.get('versions', "\{\}")
+
created_after = self.request.query_params.get('created_after', '')
created_before = self.request.query_params.get('created_before', '')
started_after = self.request.query_params.get('started_after', '')
@@ -342,6 +347,17 @@ def get_queryset(self):
userids = [int(user) for user in users if user.isdigit()]
queryset = queryset.filter(owner__in=userids)
+ if versions != "\{\}":
+ try:
+ version_dict = json.loads(versions)
+ except ValueError:
+ version_dict = {}
+ f = Q()
+ for key, values in version_dict.iteritems():
+ for value in values:
+ f = f | Q(container__version__contains={key: value})
+ queryset = queryset.filter(f)
+
if created_after != '':
created_after_date = parse_date(created_after)
if created_after_date:
@@ -531,6 +547,18 @@ def export_all(self, request):
resp['Content-Disposition'] = 'attachment; filename=Delft3DGTFiles.zip'
return resp
+ @list_route(methods=["get"])
+ def versions(self, request):
+ queryset = Container.objects.all()
+
+ resp = {}
+ for container in queryset:
+ for key, val in container.version.iteritems():
+ resp.setdefault(key, set([])).add(val)
+
+ return Response(resp)
+
+
class SearchFormViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows search forms to be viewed.