Hello,
I am coming to you because we spend all the afternoon to try to solve that issue.
I created an Rest API with Django Rest Framework.
I use the verb GET as the following http://127.0.0.1:8080/api/map/sensor/1/
My goal is to get all measure of the sensor with the ID 1.
my project/urls.py contain the following
from django.contrib import admin
from django.urls import path, include
#from map.viewsets import MarkerViewSet
urlpatterns = [
path('', include('map.urls')),
path('admin/', admin.site.urls),
path('map/', include('map.urls')),
path('api/map/', include('map.urlsapi')),
]
I created a urls file for the apis
from django.urls import path
from . import viewsapi
from map.viewsets import MarkerViewSet
app_name="map"
urlpatterns = [
path("field/<int:idfield>/", MarkerViewSet.as_view({'get': 'list'}), name="marker_view_set"), # Work with Django Rest Framework
path('sensor/<int:idsensor>/', viewsapi.sensor, name='apiSensor'), # Api classic a Django
]
I also created a view file for the api, named viewsapi.py and here the content
from django.http import JsonResponse
from rest_framework.parsers import JSONParser
from datetime import date, timedelta
from .models import Stations, Measures, Sensors
from .serializers import StationsSerializer,MeasuresSerializer
import pickle
def sensor(request, idsensor):
if(request.method == 'GET'):
# Get the last measure date/time for that sensor
latest_measure = Measures.objects.filter(sensors_id_sensor=idsensor).order_by('-measure_created').first()
# Get all measures from 3 days before the last measure
sensor_measures = Measures.objects\
.filter(sensors_id_sensor=idsensor, measure_created__range=[latest_measure.measure_created - timedelta(days=3), latest_measure.measure_created])\
.order_by('measure_created')\
.select_related('sensors_id_sensor')
print(sensor_measures.query)
# serialize the task data
serializer = MeasuresSerializer(sensor_measures, many=True)
#print(serializer.data)
# return a Json response
return JsonResponse(serializer.data, safe=False)
elif(request.method == 'POST'):
# parse the incoming information
data = JSONParser().parse(request)
# instanciate with the serializer
serializer = SensorsSerializer(data=data)
# check if the sent information is okay
if(serializer.is_valid()):
# if okay, save it on the database
serializer.save()
# provide a Json Response with the data that was saved
return JsonResponse(serializer.data, status=201)
# provide a Json Response with the necessary error information
return JsonResponse(serializer.errors, status=400)
Finally, I have my serializer.py file and I added the following
Note, SensorsSerializer seems to be usefulness
from rest_framework_gis import serializers
from rest_framework import serializers as ser
from .models import Stations, Measures, Sensors
class SensorsSerializer(ser.ModelSerializer):
class Meta:
fields = ("id_sensor","sensor_name")
model = Sensors
class MeasuresSerializer(ser.ModelSerializer):
"""
sensor_name = ser.SlugRelatedField(
many=False,
read_only=True,
slug_field='id_sensor'
)
"""
# that's a try, but I am not sure, it helps
sensor_name=SensorsSerializer(
many=True,
read_only=True
)
class Meta:
fields = ("sensor_name","id_measure","sensors_id_sensor", "value", "measure_created")
model = Measures
Description of the problem
If I load the url http://127.0.0.1:8080/api/map/sensor/1/
I get the following result
That’s fine, but I need to know the name of the sensor. Then I should see an additional line sensor_name:"bud 1"
Now, if you return to viewsapi.py file, there is print print(sensor_measures.query)
and it prints the following
SELECT `measures`.`id_measure`, `measures`.`sensors_id_sensor`, `measures`.`collections_id_collection`, `measures`.`value`, `measures`.`measure_created`, `sensors`.`id_sensor`, `sensors`.`stations_id_station`, `sensors`.`sensor_types_id_sensor_type`, `sensors`.`sensor_name`, `sensors`.`sensor_longname`, `sensors`.`sensor_description`, `sensors`.`sensor_active`, `sensors`.`sensor_created`, `sensors`.`chart_style_id_chart_style`, `sensors`.`chart_pointStyle_id_chart_pointStyle`, `sensors`.`chart_borderWidth`, `sensors`.`chart_fill`, `sensors`.`chart_showLine`, `sensors`.`chart_pointRadius`, `sensors`.`chart_pointHoverRadius`, `sensors`.`chart_backgroundColor_id_chart_backgroundColor`, `sensors`.`chart_borderColor_id_chart_borderColor` FROM `measures` INNER JOIN `sensors` ON (`measures`.`sensors_id_sensor` = `sensors`.`id_sensor`) WHERE (`measures`.`measure_created` BETWEEN 2021-04-27 12:57:05 AND 2021-04-30 12:57:05 AND `measures`.`sensors_id_sensor` = 1) ORDER BY `measures`.`measure_created` ASC
[30/Aug/2022 20:02:13] "GET /api/map/sensor/1/ HTTP/1.1" 200 32970
we can read that the jointure is done with
INNER JOIN `sensors` ON (`measures`.`sensors_id_sensor` = `sensors`.`id_sensor`)
and we can see the sensor name
`sensors`.`sensor_name`, `sensors`.`sensor_longname`
It look that all work fine.
Now, I returned to my serialzer file and I added sensor_name
class MeasuresSerializer(ser.ModelSerializer):
"""
sensor_name = ser.SlugRelatedField(
many=False,
read_only=True,
slug_field='id_sensor'
)
"""
sensor_name=SensorsSerializer(
many=True,
read_only=True
)
class Meta:
fields = ("id_measure", "sensor_name", "sensors_id_sensor", "collections_id_collection", "value", "measure_created")
model = Measures
but the sensor name is not printed. why?
I have the same result as you can see in the attached picture, above.
I also tried to add
sensors.sensor_name
but I got an error
Field name
sensors.sensor_name
is not valid for modelMeasures
.
Then, I tried to add
sensors_id_sensor.sensor_name
with the same error
Then I suppose that sensor_name
is best way
class MeasuresSerializer(ser.ModelSerializer):
"""
sensor_name = ser.SlugRelatedField(
many=False,
read_only=True,
slug_field='id_sensor'
)
"""
sensor_name=SensorsSerializer(
many=True,
read_only=True
)
class Meta:
fields = ("id_measure", "sensor_name", "sensors_id_sensor", "collections_id_collection", "value", "measure_created")
model = Measures
but why it does not print sensor_name
, and then how can I do that? What did I miss?
Many thank for your help