Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
518 views
in Technique[技术] by (71.8m points)

python - How to add data to nested serializers?

I'm trying to add data to my database by rest API and I have some problems with adding the data. So basically I have added this data from the admin page, but I want to add this from my other python by using requests. When I'm sending post request it shows me that it has been added, but sensor array is empty

[
    {
        "id": 1,
        "name": "Stacja 1",
        "delay_time": 123,
        "sensor": [
            {
                "id": 1,
                "name": "DS18B20",
                "type": "temperature",
                "date_created": "2020-06-26T16:30:28.657804Z",
                "value": 123.0,
                "index": 0
            },
            {
                "id": 2,
                "name": "DHT22",
                "type": "Humidity",
                "date_created": "2020-06-26T16:30:44.043847Z",
                "value": 1233.0,
                "index": 1
            },
            {
                "id": 3,
                "name": "DS18B20",
                "type": "temperature",
                "date_created": "2020-06-26T16:37:07.304961Z",
                "value": 1233.0,
                "index": 0
            }
        ]
    },
    {
        "id": 2,
        "name": "Stacja 1",
        "delay_time": 300,
        "sensor": []
    }
]

models.py

from django.db import models
class Sensor(models.Model):
    name = models.CharField(max_length=20, default='null', blank=True)
    type = models.CharField(max_length=20, default='null', blank=True)
    date_created = models.DateTimeField(auto_now_add=True, null=True)
    value = models.FloatField(null=True)
    index = models.IntegerField(null=True)

    def __str__(self):
        return str(self.name) + ' ' + str(self.type) + ' ' + ' index:' + str(self.index) + ' value:' + str(self.value)


class Station(models.Model):
    name = models.CharField(max_length=20, default='null', blank=True)
    delay_time = models.IntegerField(null=True)
    sensor = models.ManyToManyField(Sensor, null=True, default='null', blank=True)

serializers.py

from rest_framework import serializers
from .models import Sensor, Station


class SensorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Sensor
        fields = '__all__'


class StationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Station
        fields = '__all__'
        depth = 1


adddata.py

import json
import requests
import serial
import time
ser = serial.Serial(

    port='/dev/ttyS0',
    baudrate = 9600,
    bytesize=serial.EIGHTBITS,
    stopbits=serial.STOPBITS_ONE,
    parity=serial.PARITY_NONE,
    timeout=1,
    )

payload={
    "username":["xxxxx"],
    "password":["xxxxxxxxx"]
}

while 1:
    x = ser.readline()
    try:
        payload2 = json.loads(x)
        r = requests.post('http://192.168.1.16/api/token/', data=payload)
        jsondata = r.json()
        headers = {}
        headers['Authorization'] = 'Bearer ' + jsondata['access']
        print(jsondata['access'])
        r = requests.post('http://192.168.1.16/data/station/', headers=headers, data=payload2)
        print(r.text)
    except:
    continue



payload2 looks like

{
  "name": "Stacja 1",
  "delay_time": 300,
  "sensor": [
    {
      "name": "DS18B20",
      "type": "temperature",
      "value": 26.5,
      "index": 0
    },
    {
      "name": "DHT22",
      "type": "temperature",
      "value": 26.5,
      "index": 1
    },
    {
      "name": "DHT22",
      "type": "humidity",
      "value": 66,
      "index": 1
    },
    {
      "name": "battery",
      "type": "voltage",
      "value": 2.104492,
      "index": 2
    }
  ]
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I have tried for single station and multiple sensors, but I guess you will be able to modify it accordingly.

dataset

{
  "name": "Stacja 1",
  "delay_time": 300,
  "sensors": [
    {
      "name": "DHT22",
      "type": "temperature",
      "value": 26.5,
      "index": 1
    },
    {
      "name": "DHT22",
      "type": "humidity",
      "value": 66,
      "index": 1
    },
    {
      "name": "battery",
      "type": "voltage",
      "value": 2.104492,
      "index": 2
    }
  ]
}

serializers.py

class SensorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Sensor
        fields = '__all__'


class StationSerializer(serializers.ModelSerializer):
    sensors = SensorSerializer(many=True)

    class Meta:
        model = Station
        fields = '__all__'
    
    def create(self, validated_data):
        sensor_data = validated_data.pop('sensors')
        station = Station.objects.create(**validated_data)
        station.save()
        for sensor in sensor_data:
            s = Sensor.objects.create(**sensor)
            station.sensors.add(s.id)
        
        return station

Django docs suggests, object needs to saved before associating it with any model in case of ManyToManyField. So your station object needs to be saved before you add ManyToMany relation to it.

And here is my views.py

class AddStationAndSensorsView(CreateAPIView):
    serializer_class = StationSerializer

    def post(self, request):
        serializer = StationSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'message': ['Added']}, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE)

NOTE: I have renamed sensor to sensors in Station model.

models.py

from django.db import models


class Sensor(models.Model):
    name = models.CharField(max_length=20, default='null', blank=True)
    type = models.CharField(max_length=20, default='null', blank=True)
    date_created = models.DateTimeField(auto_now_add=True, null=True)
    value = models.FloatField(null=True)
    index = models.IntegerField(null=True)

    def __str__(self):
        return str(self.name) + ' ' + str(self.type) + ' ' + ' index:' + str(self.index) + ' value:' + str(self.value)


class Station(models.Model):
    name = models.CharField(max_length=20, default='null', blank=True)
    delay_time = models.IntegerField(null=True)
    sensors = models.ManyToManyField(Sensor, null=True, default='null', blank=True)

    def __str__(self):
        return self.name

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...