How to add data to nested serializers?

大城市里の小女人 提交于 2020-07-28 04:44:12

问题


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
    }
  ]
}

回答1:


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



回答2:


Try adding a PrimaryKeyRelatedField to your Station serializer:

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


来源:https://stackoverflow.com/questions/62603654/how-to-add-data-to-nested-serializers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!