0

I am working with Django and I need to create an API to retrieve the measures according to the type of sensors, depending of three tables (image of the Schema of my tables)

  • Measures contains all measures according to an ID of the sensors
  • Sensors contains the sensor information and the type of the sensor
  • sensor_types contains the information of the type (type name, unit, etc)

I need to know (at least) the sensor name and ID, the type of the sensor and the measures for the sensors, and the unit of the measures.

I first tried to retrieve the sensor information and the type the sensor belong to:

class TypeViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API: return the measures of several sensors according to a type of sensors and a date range.
    A type is generaly sensors with the same unit (°C, %, kPa)
    """
    # See serializers.py
    serializer_class = TypesSerializer

    def get_queryset(self):
        # get the params
        idt = self.kwargs['idtype']
        # get the date "from"
        start = self.request.query_params.get('start')
        # get the date "to"
        end = self.request.query_params.get('end')

        type = SensorTypes.objects.filter(id_sensor_type=idt)

        sensors = Sensors.objects.filter(sensor_types_id_sensor_type=idt)\
            .select_related('sensor_types_id_sensor_type')

        print(sensors.query)
        return sensors

My TypesSerializer file look like:

class SensorTypeSerializer(ser.ModelSerializer):
    class Meta:
        fields = ("id_sensor_type","sensor_type_name","sensor_type_longname","measure_unit")
        model = SensorTypes


class TypesSerializer(ser.ModelSerializer):

    sensor_types_id_sensor_type=SensorTypeSerializer(
        read_only=True
    )

    #"sensor_type_name", "measure_unit",
    class Meta:
        fields = ("id_sensor","sensor_name","sensor_types_id_sensor_type")
        model = Sensors

and I have this result (you only see two sensors but there are more bellow. (image of the result)

If now, you look at:

{
        "id_sensor": 1,
        "sensor_name": "b1",
        "sensor_types_id_sensor_type": {
            "id_sensor_type": 2,
            "sensor_type_name": "te",
            "sensor_type_longname": "Températures",
            "measure_unit": "°C"
        }
    },

I need to have all measures for that sensor. (Later, I will add a date range)

My problem I guess you understand my need, but I do not know if I started well and I do not know how to add a second join to get the measures from the Measures table.

I am a bit confuse, because previously I could retrieve the measures according to a station ID as the following:

class SensorViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API: return the measures of a sensors according to the ID of the sensor and a date range
    """
    # See serializers.py
    serializer_class = MeasuresSerializer

    def get_queryset(self):
        #get the params
        ids = self.kwargs['idsensor']
        # get the date "from"
        start = self.request.query_params.get('start')
        # get the date "to"
        end = self.request.query_params.get('end')

        # if param end (from) is empty or does not exist
        if end is None or len(end) <= 0:
            # Get the last saved measure date/time of a sensor
            latest_measure = Measures.objects.filter(sensors_id_sensor=ids).order_by('-measure_created').first()
            #save the date
            end = latest_measure.measure_created
        else:
            # get the date from the param end, create an object and save the value to end
            end = datetime.strptime(end, '%Y-%m-%d %H:%M:%S')

        # if the param start (from) is empty or does not exist
        if start is None or len(start) <= 0:
            # get the date of the latest measure minus 3 days and save it to start
            start = end - timedelta(days=3)
        else:
            # get the value from the param start, create an object and save it to start
            start = datetime.strptime(start, '%Y-%m-%d %H:%M:%S')

        # Get all measures from the date range
        sensor_measures = Measures.objects \
            .filter(sensors_id_sensor=ids,
                    measure_created__range=[start,end]) \
            .order_by('measure_created') \
            .select_related('sensors_id_sensor')

        #print(sensor_measures)
        return sensor_measures

and as you can see, I first query the measures table with a select_related to the Sensors table. But now, I need to filter the sensors according to the id of the type, and to get information about the type as measure_unit.

My question is how to "include" the Sensor_types table to my queryset?

pierrot10
  • 1
  • 3

2 Answers2

0

Aïe, I just realized, the task is a bit more complex.

I also have to filter the sensors of a station according to a field If you look at that picture

that picture

You can see, there is a relationship between the sensors and the stations table. The Stations table contains a field fields_id_field, and I need to filter the sensors that belong to a station which belong to a selected field.

For that reason I changed the url requets to

http://127.0.0.1:8080/api/map/field/1/type/2/?start=&end=2022-05-21%2010:10:10

my path look like

path("field/<int:idfield>/type/<int:idtype>/", TypeViewSet.as_view({'get': 'list'}), name="type_view_set"),

and I get the params values as the following

idt = self.kwargs['idtype']
idf = self.kwargs['idfield']

Now, my api need to retrieve the measures according to 4 tables

  • Measures contains all measures according to an ID of the sensors
  • Sensors contains the sensor information and the type of the sensor
  • sensor_types contains the information of the type (type name, unit, etc)
  • Stations contains the fields_id_field

I would really appreciate your help because I really have no idea how can create a queryset on 4 tables

  • Stations tables is needed to filter the queryset by field
  • sensor_types table is needed to filter queryset by type
  • Measures table is need to retrieve all measures by sensors (a sensor is attached to a station)

Many thanks for any help you can give me to archive my goal!! Feel free to ask me more detail, if I missed some information which can help you to better understand my script.

pierrot10
  • 1
  • 3
0

I solved the problem as the follwoing

class TypeViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API: return the measures of several sensors according to a type of sensors for a selected field, and a date range.
    (A type is generally sensors with the same unit (°C, %, kPa))
    The returned value are shorted 1) by stations ASC, then by sensors (ASC) and by date (ASC)
    If the time 'end' is empty, the today time will be considered
    If the time 'start' is empty, the start time will take the value of the end time, minus 3 days.
    Time is UTC zone (Universal Time Coordinated)
    """
    # See serializers.py
    serializer_class = MeasuresSerializer

    def get_queryset(self):
        # get the params
        idt = self.kwargs['idtype']
        idf = self.kwargs['idfield']
        # get the date "from"
        start = self.request.query_params.get('start')
        # get the date "to"
        end = self.request.query_params.get('end')

        if end is None or len(end) <= 0:
            end = datetime.datetime.now()
        else:
            end = datetime.strptime(end, '%Y-%m-%d %H:%M:%S')

        if start is None or len(start) <= 0:
            start = end - timedelta(days=3)
        else:
            start = datetime.strptime(start, '%Y-%m-%d %H:%M:%S')

        measures = Measures.objects.filter(
            sensors_id_sensor__stations_id_station__fields_id_field=idf,
            sensors_id_sensor__sensor_types_id_sensor_type=idt,
            sensors_id_sensor__sensor_active=1,
            measure_created__range=[start, end]
        ).order_by(
                'sensors_id_sensor__stations_id_station',
                'sensors_id_sensor',
                'measure_created',
                )

        #print(measures.query)
        return measures

Would have done better? (if yes, interested to know :) )

pierrot10
  • 1
  • 3