Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializer update #197

Merged
merged 10 commits into from
May 6, 2017
6 changes: 3 additions & 3 deletions backend/promis/backend_api/fixtures/init_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,21 @@
"model": "backend_api.device",
"pk": 1,
"fields": {
"satellite": 1
"space_project": 1
}
},
{
"model": "backend_api.device",
"pk": 2,
"fields": {
"satellite": 1
"space_project": 1
}
},
{
"model": "backend_api.device",
"pk": 3,
"fields": {
"satellite": 1
"space_project": 1
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion backend/promis/backend_api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def __str__(self):


class Device(TranslatableModel):
satellite = ForeignKey('Space_project')
space_project = ForeignKey('Space_project')

translations = TranslatedFields(
name = TextField(),
Expand Down
227 changes: 80 additions & 147 deletions backend/promis/backend_api/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from rest_framework.fields import ReadOnlyField, SerializerMethodField
from rest_framework.reverse import reverse
from djsw_wrapper.serializers import SwaggerHyperlinkedRelatedField
from hvad.contrib.restframework import TranslatableModelSerializer
from hvad.contrib.restframework import TranslatableModelSerializer, HyperlinkedTranslatableModelSerializer
from rest_framework_gis.serializers import GeoModelSerializer
from django.contrib.gis.geos import GEOSGeometry, GEOSException
import json
Expand All @@ -13,125 +13,87 @@
from django.contrib.auth.models import Group
from backend_api import helpers
import util.parsers
import util.unix_time

class LookupById:
'''Shortcut to include extra_kwargs to every Meta class'''
extra_kwargs = { 'url': { 'lookup_field': 'id' } }

class SessionsSerializer(serializers.ModelSerializer):
# TODO: Spike! @lyssdod, correct this
# measurements = SwaggerHyperlinkedRelatedField(many = True, view_name = 'measurement-detail', read_only = True)
measurements = SerializerMethodField()

geo_line = serializers.SerializerMethodField()
time = serializers.SerializerMethodField()

# TODO: Spike! @lyssdod, correct this
def get_measurements(self, obj):
meas = models.Measurement.objects.filter(session = obj)
#TODO: SPIKE: remove below hard code and replace to related view path.
ret_val = []
for m in meas:
ret_val.append(self.context['request'].build_absolute_uri('/en/api/measurements/' + str(m.id)))

return ret_val


def get_geo_line(self, obj):
# Just in case for the future
#return obj.geo_line.wkb.hex()

# TODO: study whether pre-building the list or JSON would speed up things
return util.parsers.wkb(obj.geo_line.wkb) # <- Generator

def get_time(self, obj):
ret_val = {}
ret_val['begin'] = str(obj.time_begin.isoformat())
ret_val['end'] = str(obj.time_end.isoformat())

return ret_val


class Meta:
model = models.Session
fields = ('id', 'space_project', 'orbit_code', 'geo_line', 'time', 'measurements')
geo_field = 'geo_line'

# TODO: merge with the class above
class CompactSessionsSerializer(serializers.ModelSerializer):
time = serializers.SerializerMethodField()

def get_geo_line(self, obj):
return util.parsers.wkb(obj.geo_line.wkb)
def get_time(self, obj):
return { 'begin': obj.time_begin.isoformat(),
'end': obj.time_end.isoformat() }

def __init__(self, *args, need_geo_line=True, **kwargs):
super().__init__(*args, **kwargs)
if need_geo_line:
self.fields.update({ "geo_line": serializers.SerializerMethodField() })

class Meta:
model = models.Session
fields = ('time',)

class SpaceProjectsSerializer(TranslatableModelSerializer):
timelapse = serializers.SerializerMethodField()

def get_timelapse(self, obj):
ret_val = {}
ret_val['begin'] = str(obj.date_start.isoformat())
ret_val['end'] = str(obj.date_end.isoformat())
# TODO: start and end are a DATE not DATETIME, but we convert them implicitly
return { 'start': util.unix_time.datetime_to_utc(obj.date_start),
'end': util.unix_time.datetime_to_utc(obj.date_end) }

return ret_val

class Meta:
class Meta(LookupById):
model = models.Space_project
fields = ('id', 'name', 'description', 'timelapse')
fields = ('id', 'url', 'name', 'description', 'timelapse')


class ChannelsSerializer(TranslatableModelSerializer):
class Meta:
fields = ('id', 'name', 'description',)
class Meta(LookupById):
fields = ('id', 'url', 'name', 'description')
model = models.Channel


class ParametersSerializer(TranslatableModelSerializer):
channel = SwaggerHyperlinkedRelatedField(many = False, read_only = True, view_name = 'channel-detail')

class Meta(LookupById):
fields = ('id', 'url', 'name', 'description', 'channel')
model = models.Parameter


class DevicesSerializer(TranslatableModelSerializer):
satellite = SpaceProjectsSerializer(many = False)
channels = ChannelsSerializer(many = True)
space_project = SwaggerHyperlinkedRelatedField(many = False, read_only = True, view_name = 'space_project-detail')
channels = SwaggerHyperlinkedRelatedField(many = True, read_only = True, view_name = 'channel-detail')

class Meta:
class Meta(LookupById):
model = models.Device
fields = ('id', 'name', 'description', 'satellite', 'channels')
fields = ('id', 'url', 'name', 'description', 'space_project', 'channels')

class FunctionsSerializer(TranslatableModelSerializer):
class Meta:
fields = ('__all__')
model = models.Function

class UnitsSerializer(TranslatableModelSerializer):
class Meta:
fields = ('__all__')
model = models.Unit
class SessionsSerializer(serializers.ModelSerializer):
# TODO: STUB, see #196
#measurements = SwaggerHyperlinkedRelatedField(many = True, read_only = True, view_name = 'measurement-detail')
# cut from here:
measurements = SerializerMethodField()
def get_measurements(self, obj):
return (self.context['request'].build_absolute_uri('/api/measurements/' + str(m.id))
for m in models.Measurement.objects.filter(session = obj))
# to here ^

class ValuesSerializer(TranslatableModelSerializer):
class Meta:
fields = ('__all__')
model = models.Value
space_project = SwaggerHyperlinkedRelatedField(many = False, read_only = True, view_name = 'space_project-detail')

class ParametersSerializer(TranslatableModelSerializer):
# TODO: fix the bug
# channel = HyperlinkedRelatedField(many = False, view_name = 'channel-detail', read_only = True)
channel = ChannelsSerializer()
class Meta:
fields = ('id', 'name', 'description', 'channel')
model = models.Parameter
geo_line = serializers.SerializerMethodField()
time = serializers.SerializerMethodField()

def get_geo_line(self, obj):
# Just in case for the future
#return obj.geo_line.wkb.hex()

'''class QuicklookHyperlink(serializers.HyperlinkedRelatedField):
view_name = 'document-detail'
read_only = True
# TODO: study whether pre-building the list or JSON would speed up things
return util.parsers.wkb(obj.geo_line.wkb) # <- Generator

queryset = models.Document.objects.all()
def get_time(self, obj):
# TODO: change to time_start in model for consistency
return { 'start': util.unix_time.datetime_to_utc(obj.time_begin),
'end': util.unix_time.datetime_to_utc(obj.time_end) }


class Meta(LookupById):
model = models.Session
fields = ('id', 'url', 'space_project', 'orbit_code', 'geo_line', 'time', 'measurements')

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# If we are serializing a list of sessions, don't include the geo_line
if type(args[0]) is list:
self.fields.pop('geo_line')

def get_object
'''

def _context_function_call(self, *args):
'''
Expand Down Expand Up @@ -199,72 +161,43 @@ class PlainTextRenderer:
def render(self, data, media_type=None, renderer_context=None):
return "\n".join(data)

#TODO: class below need some refactoring.....
class DownloadViewSerializer(serializers.ModelSerializer):
chn_quicklook = serializers.SerializerMethodField()
par_quicklook = serializers.SerializerMethodField()

channel_doc = serializers.SerializerMethodField()
parameter_doc = serializers.SerializerMethodField()

class Meta:
fields = ('chn_quicklook', 'par_quicklook', 'channel_doc', 'parameter_doc')
model = models.Measurement

def get_chn_quicklook(self, obj):
id = obj.id
#TODO: SPIKE: remove below hard code and replace to related view path.
return self.context['request'].build_absolute_uri('/en/api/quicklook/' + str(id) + '/channel')

def get_par_quicklook(self, obj):
id = obj.id
#TODO: SPIKE: remove below hard code and replace to related view path.
return self.context['request'].build_absolute_uri('/en/api/quicklook/' + str(id) + '/parameter')

def get_channel_doc(self, obj):
id = obj.id
#TODO: SPIKE: remove below hard code and replace to related view path.
return self.context['request'].build_absolute_uri('/en/api/download/' + str(id) + '/channel')

def get_parameter_doc(self, obj):
id = obj.id
#TODO: SPIKE: remove below hard code and replace to related view path.
return self.context['request'].build_absolute_uri('/en/api/download/' + str(id) + '/parameter')

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)

user = self.context['request'].user
if not (helpers.UserInGroup(user, 'level1') or helpers.IsSuperUser(user)):
self.fields.pop('channel_doc')
self.fields.pop('chn_quicklook')

class MeasurementsSerializer(serializers.ModelSerializer):
session = SwaggerHyperlinkedRelatedField(many = False, view_name = 'session-detail', read_only = True)
channel = SwaggerHyperlinkedRelatedField(many = False, view_name = 'channel-detail', read_only = True)
parameter = SwaggerHyperlinkedRelatedField(many = False, view_name = 'parameter-detail', read_only = True)
data = serializers.SerializerMethodField()
channel_quicklook = serializers.SerializerMethodField()
channel_download = serializers.SerializerMethodField()
parameter_quicklook = serializers.SerializerMethodField()
parameter_download = serializers.SerializerMethodField()


class Meta:
fields = ('session', 'parameter', 'channel', 'sampling_frequency', 'min_frequency', 'max_frequency', 'data')
class Meta(LookupById):
# TODO: add 'url' here, currently it's broken, see #196
fields = ('id', 'session', 'parameter', 'channel', 'sampling_frequency', 'min_frequency', 'max_frequency', 'channel_quicklook', 'channel_download', 'parameter_quicklook', 'parameter_download')
model = models.Measurement

def get_data(self, obj):
id = obj.channel_doc.id
#TODO: SPIKE: remove below hard code and replace to related view path.
return self.context['request'].build_absolute_uri('/en/api/download/' + str(id))
#TODO: SPIKE: remove below hard code and replace to related view path.
def construct_data_url(self, obj, source, action):
id = getattr(obj, source + "_doc").id
return self.context['request'].build_absolute_uri('/api/%s/%d/%s' % (action, id, source))

def get_channel_quicklook(self, obj):
return self.construct_data_url(obj, "channel", "quicklook")
def get_channel_download(self, obj):
return self.construct_data_url(obj, "channel", "download")
def get_parameter_quicklook(self, obj):
return self.construct_data_url(obj, "parameter", "quicklook")
def get_parameter_download(self, obj):
return self.construct_data_url(obj, "parameter", "download")
# cut here ^

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)


user = self.context['request'].user

if not (helpers.UserInGroup(user, 'level1') or helpers.IsSuperUser(user)):
self.fields.pop('channel')
self.fields.pop('channel_download')


class UserSerializer(serializers.ModelSerializer):
Expand Down
17 changes: 0 additions & 17 deletions backend/promis/backend_api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,8 @@
docrout.register(r'api/quicklook', views.QuicklookView)
docrout.register(r'api/download', views.DownloadData)

'''
#== db view ==
#TODO: This is used only for debugging, and should be removed
#TODO: Remove it

dbview = SimpleRouter()
dbview.register(r'functions', views.FunctionsView)
dbview.register(r'documents', views.DocumentsView)
dbview.register(r'parameters', views.ParametersView)

#=============
'''

urlpatterns = router.urls + userreg.urls + [
url('^api-auth/', include('rest_framework.urls', namespace = 'rest_framework')),
url(r'^user/update/$', views.UserUpdate),
] + docrout.urls


# + dbview.urls

#print(urlpatterns)
Loading